inline bool is_ack() const
{ return (th_flags & TH_ACK); }
+ inline bool is_psh() const
+ { return (th_flags & TH_PUSH); }
+
inline bool is_rst() const
{ return (th_flags & TH_RST); }
#include "stream_tcp_unit_test.h"
// SYN PACKET
-// IP 192.168.0.89.9012 > p3nlh044.shr.prod.phx3.secureserver.net.http: Flags [S], seq 9050, win 8192, length 0
- uint8_t cooked_syn[] = "\x00\x21\x91\x01\xb2\x48\xaa\x00\x04\x00\x0a\x04\x08\x00\x45\x00\x00\x28\x00\x01\x00\x00\x40\x06\x88\x96\xc0\xa8\x00\x59\x48\xa7\xe8\x90\x23\x34\x00\x50\x00\x00\x23\x5a\x00\x00\x00\x00\x50\x02\x20\x00\x56\xcb\x00\x00";
+// IP 192.168.0.89.9012 > p3nlh044.shr.prod.phx3.secureserver.net.http: Flags [S], seq 9050, win
+// 8192, length 0
+uint8_t cooked_syn[] =
+ "\x00\x21\x91\x01\xb2\x48\xaa\x00\x04\x00\x0a\x04\x08\x00\x45\x00\x00\x28\x00\x01\x00\x00\x40\x06\x88\x96\xc0\xa8\x00\x59\x48\xa7\xe8\x90\x23\x34\x00\x50\x00\x00\x23\x5a\x00\x00\x00\x00\x50\x02\x20\x00\x56\xcb\x00\x00";
// SYN-ACK PACKET
-// IP p3nlh044.shr.prod.phx3.secureserver.net.http > 192.168.0.89.9012: Flags [S.], seq 9025, ack 9051, win 8192, length 0
- uint8_t cooked_syn_ack[] = "\xff\xff\xff\xff\xff\xff\x00\x00\x00\x00\x00\x00\x08\x00\x45\x00\x00\x28\x00\x01\x00\x00\x40\x06\x88\x96\x48\xa7\xe8\x90\xc0\xa8\x00\x59\x00\x50\x23\x34\x00\x00\x23\x41\x00\x00\x23\x5b\x50\x12\x20\x00\x33\x79\x00\x00";
+// IP p3nlh044.shr.prod.phx3.secureserver.net.http > 192.168.0.89.9012: Flags [S.], seq 9025, ack
+// 9051, win 8192, length 0
+uint8_t cooked_syn_ack[] =
+ "\xff\xff\xff\xff\xff\xff\x00\x00\x00\x00\x00\x00\x08\x00\x45\x00\x00\x28\x00\x01\x00\x00\x40\x06\x88\x96\x48\xa7\xe8\x90\xc0\xa8\x00\x59\x00\x50\x23\x34\x00\x00\x23\x41\x00\x00\x23\x5b\x50\x12\x20\x00\x33\x79\x00\x00";
// ACK PACKET
-// IP 192.168.0.89.9012 > p3nlh044.shr.prod.phx3.secureserver.net.http: Flags [.], ack 1, win 8192, length 0
- uint8_t cooked_ack[] = "\x00\x21\x91\x01\xb2\x48\xaa\x00\x04\x00\x0a\x04\x08\x00\x45\x00\x00\x28\x00\x01\x00\x00\x40\x06\x88\x96\xc0\xa8\x00\x59\x48\xa7\xe8\x90\x23\x34\x00\x50\x00\x00\x23\x5b\x00\x00\x23\x42\x50\x10\x20\x00\x33\x7a\x00\x00";
+// IP 192.168.0.89.9012 > p3nlh044.shr.prod.phx3.secureserver.net.http: Flags [.], ack 1, win 8192,
+// length 0
+uint8_t cooked_ack[] =
+ "\x00\x21\x91\x01\xb2\x48\xaa\x00\x04\x00\x0a\x04\x08\x00\x45\x00\x00\x28\x00\x01\x00\x00\x40\x06\x88\x96\xc0\xa8\x00\x59\x48\xa7\xe8\x90\x23\x34\x00\x50\x00\x00\x23\x5b\x00\x00\x23\x42\x50\x10\x20\x00\x33\x7a\x00\x00";
// FIXIT - this is not a FIN PACKET yet...
-// IP 192.168.0.89.9012 > p3nlh044.shr.prod.phx3.secureserver.net.http: Flags [.], ack 1, win 8192, length 0
- uint8_t cooked_fin[] = "\x00\x21\x91\x01\xb2\x48\xaa\x00\x04\x00\x0a\x04\x08\x00\x45\x00\x00\x28\x00\x01\x00\x00\x40\x06\x88\x96\xc0\xa8\x00\x59\x48\xa7\xe8\x90\x23\x34\x00\x50\x00\x00\x23\x5b\x00\x00\x23\x42\x50\x10\x20\x00\x33\x7a\x00\x00";
+// IP 192.168.0.89.9012 > p3nlh044.shr.prod.phx3.secureserver.net.http: Flags [.], ack 1, win 8192,
+// length 0
+uint8_t cooked_fin[] =
+ "\x00\x21\x91\x01\xb2\x48\xaa\x00\x04\x00\x0a\x04\x08\x00\x45\x00\x00\x28\x00\x01\x00\x00\x40\x06\x88\x96\xc0\xa8\x00\x59\x48\xa7\xe8\x90\x23\x34\x00\x50\x00\x00\x23\x5b\x00\x00\x23\x42\x50\x10\x20\x00\x33\x7a\x00\x00";
// FIXIT - this is not a RST PACKET yet...
-// IP 192.168.0.89.9012 > p3nlh044.shr.prod.phx3.secureserver.net.http: Flags [.], ack 1, win 8192, length 0
- uint8_t cooked_rst[] = "\x00\x21\x91\x01\xb2\x48\xaa\x00\x04\x00\x0a\x04\x08\x00\x45\x00\x00\x28\x00\x01\x00\x00\x40\x06\x88\x96\xc0\xa8\x00\x59\x48\xa7\xe8\x90\x23\x34\x00\x50\x00\x00\x23\x5b\x00\x00\x23\x42\x50\x10\x20\x00\x33\x7a\x00\x00";
+// IP 192.168.0.89.9012 > p3nlh044.shr.prod.phx3.secureserver.net.http: Flags [.], ack 1, win 8192,
+// length 0
+uint8_t cooked_rst[] =
+ "\x00\x21\x91\x01\xb2\x48\xaa\x00\x04\x00\x0a\x04\x08\x00\x45\x00\x00\x28\x00\x01\x00\x00\x40\x06\x88\x96\xc0\xa8\x00\x59\x48\xa7\xe8\x90\x23\x34\x00\x50\x00\x00\x23\x5b\x00\x00\x23\x42\x50\x10\x20\x00\x33\x7a\x00\x00";
// DATA PACKET
-// IP 192.168.0.89.9012 > p3nlh044.shr.prod.phx3.secureserver.net.http: Flags [P.], seq 1:43, ack 1, win 8192, length 42
- uint8_t cooked_data[] = "\x00\x21\x91\x01\xb2\x48\xaa\x00\x04\x00\x0a\x04\x08\x00\x45\x00\x00\x52\x00\x01\x00\x00\x40\x06\x88\x6c\xc0\xa8\x00\x59\x48\xa7\xe8\x90\x23\x34\x00\x50\x00\x00\x23\x5b\x00\x00\x23\x42\x50\x18\x20\x00\x14\x83\x00\x00\x47\x45\x54\x20\x2f\x20\x48\x54\x54\x50\x2f\x31\x2e\x31\x0d\x0a\x48\x6f\x73\x74\x3a\x20\x77\x77\x77\x2e\x6d\x61\x6c\x66\x6f\x72\x67\x65\x2e\x63\x6f\x6d\x0d\x0a\x0d\x0a";
+// IP 192.168.0.89.9012 > p3nlh044.shr.prod.phx3.secureserver.net.http: Flags [P.], seq 1:43, ack
+// 1, win 8192, length 42
+uint8_t cooked_data[] =
+ "\x00\x21\x91\x01\xb2\x48\xaa\x00\x04\x00\x0a\x04\x08\x00\x45\x00\x00\x52\x00\x01\x00\x00\x40\x06\x88\x6c\xc0\xa8\x00\x59\x48\xa7\xe8\x90\x23\x34\x00\x50\x00\x00\x23\x5b\x00\x00\x23\x42\x50\x18\x20\x00\x14\x83\x00\x00\x47\x45\x54\x20\x2f\x20\x48\x54\x54\x50\x2f\x31\x2e\x31\x0d\x0a\x48\x6f\x73\x74\x3a\x20\x77\x77\x77\x2e\x6d\x61\x6c\x66\x6f\x72\x67\x65\x2e\x63\x6f\x6d\x0d\x0a\x0d\x0a";
DAQ_PktHdr_t daqHdr;
static DAQ_PktHdr_t* initDaqHdr( )
{
- gettimeofday( &daqHdr.ts, NULL );
+ gettimeofday(&daqHdr.ts, NULL);
return &daqHdr;
}
-static Packet* init_packet( Flow* flow, uint32_t talker )
+static Packet* init_packet(Flow* flow, uint32_t talker)
{
Packet* pkt = new Packet;
pkt->flow = flow;
pkt->packet_flags = talker;
+ pkt->proto_bits &= ~PROTO_BIT__ETH;
pkt->pkth = initDaqHdr();
pkt->dsize = 0;
return pkt;
}
-Packet* get_syn_packet( Flow* flow )
+Packet* get_syn_packet(Flow* flow)
{
- Packet* pkt = init_packet( flow, PKT_FROM_CLIENT );
+ Packet* pkt = init_packet(flow, PKT_FROM_CLIENT);
- pkt->pkt = cooked_syn;
- pkt->ptrs.tcph = ( tcp::TCPHdr * ) ( cooked_syn + 34 );
+ pkt->pkt = cooked_syn;
+ pkt->ptrs.tcph = ( tcp::TCPHdr* )( cooked_syn + 34 );
- return pkt;
+ return pkt;
}
-Packet* get_syn_ack_packet( Flow* flow )
+Packet* get_syn_ack_packet(Flow* flow)
{
- Packet* pkt = init_packet( flow, PKT_FROM_SERVER );
+ Packet* pkt = init_packet(flow, PKT_FROM_SERVER);
- pkt->pkt = cooked_syn_ack;
- pkt->ptrs.tcph = ( tcp::TCPHdr * ) ( cooked_syn_ack + 34 );
+ pkt->pkt = cooked_syn_ack;
+ pkt->ptrs.tcph = ( tcp::TCPHdr* )( cooked_syn_ack + 34 );
- return pkt;
+ return pkt;
}
-Packet *get_ack_packet( Flow* flow )
+Packet* get_ack_packet(Flow* flow)
{
- Packet* pkt = init_packet( flow, PKT_FROM_CLIENT );
+ Packet* pkt = init_packet(flow, PKT_FROM_CLIENT);
- pkt->pkt = cooked_ack;
- pkt->ptrs.tcph = ( tcp::TCPHdr * ) ( cooked_ack + 34 );
+ pkt->pkt = cooked_ack;
+ pkt->ptrs.tcph = ( tcp::TCPHdr* )( cooked_ack + 34 );
- return pkt;
+ return pkt;
}
-Packet *get_fin_packet( Flow* flow )
+Packet* get_fin_packet(Flow* flow)
{
- Packet* pkt = init_packet( flow, PKT_FROM_CLIENT );
+ Packet* pkt = init_packet(flow, PKT_FROM_CLIENT);
- pkt->pkt = cooked_fin;
- pkt->ptrs.tcph = ( tcp::TCPHdr * ) ( cooked_fin + 34 );
+ pkt->pkt = cooked_fin;
+ pkt->ptrs.tcph = ( tcp::TCPHdr* )( cooked_fin + 34 );
- return pkt;
+ return pkt;
}
-Packet *get_rst_packet( Flow* flow )
+Packet* get_rst_packet(Flow* flow)
{
- Packet* pkt = init_packet( flow, PKT_FROM_CLIENT );
+ Packet* pkt = init_packet(flow, PKT_FROM_CLIENT);
- pkt->pkt = cooked_rst;
- pkt->ptrs.tcph = ( tcp::TCPHdr * ) ( cooked_rst + 34 );
+ pkt->pkt = cooked_rst;
+ pkt->ptrs.tcph = ( tcp::TCPHdr* )( cooked_rst + 34 );
- return pkt;
+ return pkt;
}
-Packet *get_data_packet( Flow* flow )
+Packet* get_data_packet(Flow* flow)
{
- Packet* pkt = init_packet( flow, PKT_FROM_CLIENT );
+ Packet* pkt = init_packet(flow, PKT_FROM_CLIENT);
- pkt->pkt = cooked_data;
- pkt->ptrs.tcph = ( tcp::TCPHdr * ) ( cooked_data + 34 );
- pkt->dsize = 42;
+ pkt->pkt = cooked_data;
+ pkt->ptrs.tcph = ( tcp::TCPHdr* )( cooked_data + 34 );
+ pkt->dsize = 42;
- return pkt;
+ return pkt;
}
+
#endif
#include "protocols/packet.h"
-Packet *get_syn_packet( Flow* );
-Packet *get_syn_ack_packet( Flow* );
-Packet *get_ack_packet( Flow* );
-Packet *get_fin_packet( Flow* );
-Packet *get_rst_packet( Flow* );
-Packet *get_data_packet( Flow* );
+Packet* get_syn_packet(Flow*);
+Packet* get_syn_ack_packet(Flow*);
+Packet* get_ack_packet(Flow*);
+Packet* get_fin_packet(Flow*);
+Packet* get_rst_packet(Flow*);
+Packet* get_data_packet(Flow*);
#endif
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
//--------------------------------------------------------------------------
-// tcp_segment_descriptor.cc author davis mcpherson <davmcphe@@cisco.com>
+// tcp_segment_descriptor.cc author davis mcpherson <davmcphe@cisco.com>
// Created on: Jul 30, 2015
+#include "main/snort_debug.h"
+
+#include "stream/tcp/tcp_defs.h"
+#include "protocols/tcp_options.h"
+#include "stream/tcp/tcp_event_logger.h"
#include "tcp_segment_descriptor.h"
-TcpSegmentDescriptor::TcpSegmentDescriptor( Flow* flow, Packet* pkt ) :
- flow( flow ), pkt( pkt )
-{
- direction = flow->ssn_state.direction;
+using namespace tcp;
+TcpSegmentDescriptor::TcpSegmentDescriptor(Flow* flow, Packet* pkt, TcpEventLogger* tel) :
+ flow(flow), pkt(pkt)
+{
tcph = pkt->ptrs.tcph;
- data_len = pkt->dsize;
-
src_port = ntohs(tcph->th_sport);
- dst_port = ntohs(pkt->ptrs.tcph->th_dport);
+ dst_port = ntohs(tcph->th_dport);
seq = ntohl(pkt->ptrs.tcph->th_seq);
ack = ntohl(pkt->ptrs.tcph->th_ack);
win = ntohs(pkt->ptrs.tcph->th_win);
- end_seq = seq + (uint32_t) pkt->dsize;
+ end_seq = seq + (uint32_t)pkt->dsize;
ts = 0;
+
+ // don't bump end_seq for fin here we will bump if/when fin is processed
+ if ( tcph->is_syn() )
+ {
+ end_seq++;
+ if ( !tcph->is_ack() )
+ tel->set_tcp_internal_syn_event( );
+ }
+
+ #ifdef DEBUG_STREAM_EX
+ print_tsd( );
+ #endif
}
TcpSegmentDescriptor::~TcpSegmentDescriptor()
// TODO Auto-generated destructor stub
}
+uint32_t TcpSegmentDescriptor::init_mss(uint16_t* value)
+{
+ DebugMessage(DEBUG_STREAM_STATE, "Getting MSS...\n");
+
+ TcpOptIterator iter(tcph, pkt);
+ for ( const TcpOption& opt : iter )
+ {
+ if ( opt.code == TcpOptCode::MAXSEG )
+ {
+ *value = EXTRACT_16BITS(opt.data);
+ DebugFormat(DEBUG_STREAM_STATE, "Found MSS %u\n", *value);
+ return TF_MSS;
+ }
+ }
+
+ *value = 0;
+
+ DebugMessage(DEBUG_STREAM_STATE, "No MSS...\n");
+
+ return TF_NONE;
+}
+
+uint32_t TcpSegmentDescriptor::init_wscale(uint16_t* value)
+{
+ DebugMessage(DEBUG_STREAM_STATE, "Getting wscale...\n");
+
+ TcpOptIterator iter(tcph, pkt);
+
+ // using const because non-const is not supported
+ for (const TcpOption& opt : iter)
+ {
+ if (opt.code == TcpOptCode::WSCALE)
+ {
+ *value = (uint16_t)opt.data[0];
+ DebugFormat(DEBUG_STREAM_STATE, "Found wscale %d\n", *value);
+
+ /* If scale specified in option is larger than 14,
+ * use 14 because of limitation in the math of
+ * shifting a 32bit value (max scaled window is 2^30th).
+ *
+ * See RFC 1323 for details.
+ */
+ if (*value > 14)
+ *value = 14;
+
+ return TF_WSCALE;
+ }
+ }
+
+ *value = 0;
+ DebugMessage(DEBUG_STREAM_STATE, "No wscale...\n");
+
+ return TF_NONE;
+}
+
+uint32_t TcpSegmentDescriptor::has_wscale(void)
+{
+ uint16_t wscale;
+
+ DebugMessage(DEBUG_STREAM_STATE, "Checking for wscale...\n");
+
+ return init_wscale(&wscale);
+}
+
+void TcpSegmentDescriptor::print_tsd(void)
+{
+ LogMessage("Tcp Segment Descriptor:\n");
+ LogMessage(" seq: 0x%08X\n", seq);
+ LogMessage(" ack: 0x%08X\n", ack);
+ LogMessage(" win: %d\n", win);
+ LogMessage(" end: 0x%08X\n", end_seq);
+}
+
#include "protocols/tcp.h"
#include "protocols/packet.h"
+#include "stream/tcp/tcp_event_logger.h"
+
class TcpSegmentDescriptor
{
public:
- TcpSegmentDescriptor( Flow*, Packet* );
+ TcpSegmentDescriptor(Flow*, Packet*, TcpEventLogger*);
virtual ~TcpSegmentDescriptor();
- const Flow* get_flow() const
+ uint32_t init_mss(uint16_t* value);
+ uint32_t init_wscale(uint16_t* value);
+ uint32_t has_wscale(void);
+
+ Flow* get_flow() const
{
return flow;
}
- const Packet* get_pkt() const
+ Packet* get_pkt() const
{
return pkt;
}
+
const tcp::TCPHdr* get_tcph() const
{
return tcph;
}
+ void set_seq(uint32_t seq)
+ {
+ this->seq = seq;
+ }
+
+ uint32_t get_seq() const
+ {
+ return seq;
+ }
+
uint32_t get_ack() const
{
return ack;
}
+ void set_end_seq(uint32_t end_seq)
+ {
+ this->end_seq = end_seq;
+ }
+
uint32_t get_end_seq() const
{
return end_seq;
}
- uint32_t get_seq() const
+ void set_ts(uint32_t ts)
{
- return seq;
+ this->ts = ts;
}
uint32_t get_ts() const
{
- return ts;
+ return ts;
+ }
+
+ void set_win(uint32_t win)
+ {
+ this->win = win;
}
- uint16_t get_win() const
+ uint32_t get_win() const
{
- return win;
+ return win;
}
uint16_t get_dst_port() const
uint8_t get_direction() const
{
- return direction;
- }
-
- void set_direction(uint8_t direction)
- {
- this->direction = direction;
+ return flow->ssn_state.direction;
}
uint32_t get_data_len() const
{
- return data_len;
+ return pkt->dsize;
}
- void set_data_len(uint32_t data_len)
- {
- this->data_len = data_len;
- }
+ void print_tsd(void);
private:
- Flow* flow;
+ Flow* flow;
Packet* pkt;
- uint8_t direction;
-
const tcp::TCPHdr* tcph;
- uint32_t data_len;
uint16_t src_port;
uint16_t dst_port;
uint32_t seq;
uint32_t ack;
- uint16_t win;
+ uint32_t win;
uint32_t end_seq;
uint32_t ts;
};
#endif
+
#include <iostream>
using namespace std;
-#include "tcp_state_handler.h"
-
#include "main/snort_debug.h"
+#include "tcp_state_machine.h"
+#include "tcp_state_handler.h"
+
#ifdef UNIT_TEST
#include "catch/catch.hpp"
#include "stream_tcp_unit_test.h"
#endif
-
-TcpStateHandler::TcpStateHandler() :
- tcp_event( TcpStreamTracker::TCP_MAX_EVENTS )
+TcpStateHandler::TcpStateHandler(TcpStreamTracker::TcpStates state, TcpStateMachine& tsm) :
+ tsm(&tsm), tcp_state(state), tcp_event(TcpStreamTracker::TCP_MAX_EVENTS)
{
- // TODO Auto-generated constructor stub
+ tsm.register_state_handler(state, *this);
+}
+TcpStateHandler::TcpStateHandler(void) :
+ tsm(nullptr), tcp_state(TcpStreamTracker::TCP_CLOSED),
+ tcp_event(TcpStreamTracker::TCP_MAX_EVENTS)
+{
}
TcpStateHandler::~TcpStateHandler()
{
// TODO Auto-generated destructor stub
-
}
-void TcpStateHandler::eval( TcpSegmentDescriptor &tcp_seg, TcpStreamTracker &tracker )
+bool TcpStateHandler::eval(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
{
- switch( tcp_event = tracker.get_tcp_event() )
+ bool handled = false;
+
+ switch ( tcp_event = tracker.get_tcp_event() )
{
case TcpStreamTracker::TCP_SYN_SENT_EVENT:
- syn_sent( tcp_seg, tracker );
+ handled = syn_sent(tsd, tracker);
break;
case TcpStreamTracker::TCP_SYN_RECV_EVENT:
- syn_recv( tcp_seg, tracker );
+ handled = syn_recv(tsd, tracker);
break;
case TcpStreamTracker::TCP_SYN_ACK_SENT_EVENT:
- syn_ack_sent( tcp_seg, tracker );
+ handled = syn_ack_sent(tsd, tracker);
break;
case TcpStreamTracker::TCP_SYN_ACK_RECV_EVENT:
- syn_ack_recv( tcp_seg, tracker );
+ handled = syn_ack_recv(tsd, tracker);
break;
case TcpStreamTracker::TCP_ACK_SENT_EVENT:
- ack_sent( tcp_seg, tracker );
+ handled = ack_sent(tsd, tracker);
break;
case TcpStreamTracker::TCP_ACK_RECV_EVENT:
- ack_recv( tcp_seg, tracker );
+ handled = ack_recv(tsd, tracker);
break;
case TcpStreamTracker::TCP_DATA_SEG_SENT_EVENT:
- data_seg_sent( tcp_seg, tracker );
+ handled = data_seg_sent(tsd, tracker);
break;
case TcpStreamTracker::TCP_DATA_SEG_RECV_EVENT:
- data_seg_recv( tcp_seg, tracker );
+ handled = data_seg_recv(tsd, tracker);
break;
case TcpStreamTracker::TCP_FIN_SENT_EVENT:
- fin_sent( tcp_seg, tracker );
+ handled = fin_sent(tsd, tracker);
break;
case TcpStreamTracker::TCP_FIN_RECV_EVENT:
- fin_recv( tcp_seg, tracker );
+ handled = fin_recv(tsd, tracker);
break;
case TcpStreamTracker::TCP_RST_SENT_EVENT:
- rst_sent( tcp_seg, tracker );
+ handled = rst_sent(tsd, tracker);
break;
case TcpStreamTracker::TCP_RST_RECV_EVENT:
- rst_recv( tcp_seg, tracker );
+ handled = rst_recv(tsd, tracker);
break;
case TcpStreamTracker::TCP_MAX_EVENTS:
default:
cout << "Invalid Tcp Event " << tracker.get_tcp_event() << endl;
break;
-
}
+
+ return handled;
}
-void TcpStateHandler::default_state_action(
- TcpSegmentDescriptor* tcp_seg, TcpStreamTracker* tracker, const char* func_name )
+bool TcpStateHandler::default_state_action(
+ TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker, const char* func_name)
{
#ifdef DEBUG_MSGS
- DebugFormat(DEBUG_STREAM_STATE, "Default Implementation of: %s tcp_seg: %p tracker: %p\n",
- func_name, tcp_seg, tracker );
+ DebugFormat(DEBUG_STREAM_STATE, "Default Implementation of: %s tsd: %p tracker: %p\n",
+ func_name, &tsd, &tracker);
#else
- UNUSED(tcp_seg);
+ UNUSED(tsd);
UNUSED(func_name);
#endif
- tcp_event = tracker->get_tcp_event();
+ tcp_event = tracker.get_tcp_event();
+ return false;
}
-void TcpStateHandler::syn_sent( TcpSegmentDescriptor &tcp_seg, TcpStreamTracker &tracker )
+bool TcpStateHandler::syn_sent(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
{
- default_state_action( &tcp_seg, &tracker, __func__ );
+ return default_state_action(tsd, tracker, __func__);
}
-void TcpStateHandler::syn_recv(TcpSegmentDescriptor &tcp_seg, TcpStreamTracker &tracker)
+bool TcpStateHandler::syn_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
{
- default_state_action( &tcp_seg, &tracker, __func__ );
+ return default_state_action(tsd, tracker, __func__);
}
-void TcpStateHandler::syn_ack_sent(TcpSegmentDescriptor &tcp_seg, TcpStreamTracker &tracker)
+bool TcpStateHandler::syn_ack_sent(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
{
- default_state_action( &tcp_seg, &tracker, __func__ );
+ return default_state_action(tsd, tracker, __func__);
}
-void TcpStateHandler::syn_ack_recv(TcpSegmentDescriptor &tcp_seg, TcpStreamTracker &tracker)
+bool TcpStateHandler::syn_ack_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
{
- default_state_action( &tcp_seg, &tracker, __func__ );
+ return default_state_action(tsd, tracker, __func__);
}
-void TcpStateHandler::ack_sent(TcpSegmentDescriptor &tcp_seg, TcpStreamTracker &tracker)
+bool TcpStateHandler::ack_sent(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
{
- default_state_action( &tcp_seg, &tracker, __func__ );
+ return default_state_action(tsd, tracker, __func__);
}
-void TcpStateHandler::ack_recv(TcpSegmentDescriptor &tcp_seg, TcpStreamTracker &tracker)
+bool TcpStateHandler::ack_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
{
- default_state_action( &tcp_seg, &tracker, __func__ );
+ return default_state_action(tsd, tracker, __func__);
}
-void TcpStateHandler::data_seg_sent(TcpSegmentDescriptor &tcp_seg, TcpStreamTracker &tracker)
+bool TcpStateHandler::data_seg_sent(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
{
- default_state_action( &tcp_seg, &tracker, __func__ );
+ return default_state_action(tsd, tracker, __func__);
}
-void TcpStateHandler::data_seg_recv(TcpSegmentDescriptor &tcp_seg, TcpStreamTracker &tracker)
+bool TcpStateHandler::data_seg_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
{
- default_state_action( &tcp_seg, &tracker, __func__ );
+ return default_state_action(tsd, tracker, __func__);
}
-void TcpStateHandler::fin_sent(TcpSegmentDescriptor &tcp_seg, TcpStreamTracker &tracker)
+bool TcpStateHandler::fin_sent(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
{
- default_state_action( &tcp_seg, &tracker, __func__ );
+ return default_state_action(tsd, tracker, __func__);
}
-void TcpStateHandler::fin_recv(TcpSegmentDescriptor &tcp_seg, TcpStreamTracker &tracker)
+bool TcpStateHandler::fin_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
{
- default_state_action( &tcp_seg, &tracker, __func__ );
+ return default_state_action(tsd, tracker, __func__);
}
-void TcpStateHandler::rst_sent(TcpSegmentDescriptor &tcp_seg, TcpStreamTracker &tracker)
+bool TcpStateHandler::rst_sent(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
{
- default_state_action( &tcp_seg, &tracker, __func__ );
+ return default_state_action(tsd, tracker, __func__);
}
-void TcpStateHandler::rst_recv(TcpSegmentDescriptor &tcp_seg, TcpStreamTracker &tracker)
+bool TcpStateHandler::rst_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
{
- default_state_action( &tcp_seg, &tracker, __func__ );
+ return default_state_action(tsd, tracker, __func__);
}
#ifdef UNIT_TEST
SCENARIO("TCP State Handler Base Class", "[state_handlers][stream_tcp]")
{
- // initialization code here
- Flow* flow = new Flow;
- TcpStateHandler* tsh = new TcpStateHandler;
- TcpStreamTracker* client_tracker = new TcpStreamTracker( true );
- TcpStreamTracker* server_tracker = new TcpStreamTracker( false );
-
- GIVEN("a SYN Packet")
- {
- Packet* pkt = get_syn_packet( flow );
- REQUIRE( ( pkt != nullptr ) );
-
- WHEN("SYN is sent")
- {
- TcpSegmentDescriptor* tcp_seg = new TcpSegmentDescriptor( flow, pkt );
- REQUIRE( ( tcp_seg != nullptr ) );
- client_tracker->set_tcp_event( TcpStreamTracker::TCP_SYN_SENT_EVENT );
- tsh->eval( *tcp_seg, *client_tracker );
- THEN("Event should be TCP_SYN_SENT_EVENT")
- {
- CHECK( ( tsh->get_tcp_event() == client_tracker->get_tcp_event() ) );
- }
- delete tcp_seg;
- }
-
- SECTION("SYN is received")
- {
- TcpSegmentDescriptor* tcp_seg = new TcpSegmentDescriptor( flow, pkt );
- REQUIRE( ( tcp_seg != nullptr ) );
- server_tracker->set_tcp_event( TcpStreamTracker::TCP_SYN_RECV_EVENT );
- tsh->eval( *tcp_seg, *server_tracker );
- CHECK( ( tsh->get_tcp_event() == server_tracker->get_tcp_event() ) );
- delete tcp_seg;
- }
-
- delete pkt;
- }
-
- SECTION("syn_ack_packet")
- {
- Packet* pkt = get_syn_ack_packet( flow );
- REQUIRE( ( pkt != nullptr ) );
-
- SECTION("syn_ack_sent")
- {
- TcpSegmentDescriptor* tcp_seg = new TcpSegmentDescriptor( flow, pkt );
- REQUIRE( ( tcp_seg != nullptr ) );
- client_tracker->set_tcp_event( TcpStreamTracker::TCP_SYN_ACK_SENT_EVENT );
- tsh->eval( *tcp_seg, *client_tracker );
- CHECK( ( tsh->get_tcp_event() == client_tracker->get_tcp_event() ) );
- delete tcp_seg;
- }
-
- SECTION("syn_ack_recv")
- {
- TcpSegmentDescriptor* tcp_seg = new TcpSegmentDescriptor( flow, pkt );
- REQUIRE( ( tcp_seg != nullptr ) );
- server_tracker->set_tcp_event( TcpStreamTracker::TCP_SYN_ACK_RECV_EVENT );
- tsh->eval( *tcp_seg, *server_tracker );
- CHECK( ( tsh->get_tcp_event() == server_tracker->get_tcp_event() ) );
- delete tcp_seg;
- }
-
- delete pkt;
- }
-
- SECTION("ack_packet")
- {
- Packet* pkt = get_ack_packet( flow );
- REQUIRE( ( pkt != nullptr ) );
-
- SECTION("ack_sent")
- {
- TcpSegmentDescriptor* tcp_seg = new TcpSegmentDescriptor( flow, pkt );
- REQUIRE( ( tcp_seg != nullptr ) );
- client_tracker->set_tcp_event( TcpStreamTracker::TCP_ACK_SENT_EVENT );
- tsh->eval( *tcp_seg, *client_tracker );
- CHECK( ( tsh->get_tcp_event() == client_tracker->get_tcp_event() ) );
- delete tcp_seg;
- }
-
- SECTION("ack_recv")
- {
- TcpSegmentDescriptor* tcp_seg = new TcpSegmentDescriptor( flow, pkt );
- REQUIRE( ( tcp_seg != nullptr ) );
- server_tracker->set_tcp_event( TcpStreamTracker::TCP_ACK_RECV_EVENT );
- tsh->eval( *tcp_seg, *server_tracker );
- CHECK( ( tsh->get_tcp_event() == server_tracker->get_tcp_event() ) );
- delete tcp_seg;
- }
-
- delete pkt;
- }
-
- SECTION("data_seg_packet")
- {
- Packet* pkt = get_data_packet( flow );
- REQUIRE( ( pkt != nullptr ) );
-
- SECTION("data_seg_sent")
- {
- TcpSegmentDescriptor* tcp_seg = new TcpSegmentDescriptor( flow, pkt );
- REQUIRE( ( tcp_seg != nullptr ) );
- client_tracker->set_tcp_event( TcpStreamTracker::TCP_DATA_SEG_SENT_EVENT );
- tsh->eval( *tcp_seg, *client_tracker );
- CHECK( ( tsh->get_tcp_event() == client_tracker->get_tcp_event() ) );
- delete tcp_seg;
- }
-
- SECTION("data_seg_recv")
- {
- TcpSegmentDescriptor* tcp_seg = new TcpSegmentDescriptor( flow, pkt );
- REQUIRE( ( tcp_seg != nullptr ) );
- server_tracker->set_tcp_event( TcpStreamTracker::TCP_DATA_SEG_RECV_EVENT );
- tsh->eval( *tcp_seg, *server_tracker );
- CHECK( ( tsh->get_tcp_event() == server_tracker->get_tcp_event() ) );
- delete tcp_seg;
- }
-
- delete pkt;
- }
-
- SECTION("fin_packet")
- {
- Packet* pkt = get_fin_packet( flow );
- REQUIRE( ( pkt != nullptr ) );
-
- SECTION("fin_sent")
- {
- TcpSegmentDescriptor* tcp_seg = new TcpSegmentDescriptor( flow, pkt );
- REQUIRE( ( tcp_seg != nullptr ) );
- client_tracker->set_tcp_event( TcpStreamTracker::TCP_FIN_SENT_EVENT );
- tsh->eval( *tcp_seg, *client_tracker );
- CHECK( ( tsh->get_tcp_event() == client_tracker->get_tcp_event() ) );
- delete tcp_seg;
- }
-
- SECTION("fin_recv")
- {
- TcpSegmentDescriptor* tcp_seg = new TcpSegmentDescriptor( flow, pkt );
- REQUIRE( ( tcp_seg != nullptr ) );
- server_tracker->set_tcp_event( TcpStreamTracker::TCP_FIN_RECV_EVENT );
- tsh->eval( *tcp_seg, *server_tracker );
- CHECK( ( tsh->get_tcp_event() == server_tracker->get_tcp_event() ) );
- delete tcp_seg;
- }
-
- delete pkt;
- }
-
- SECTION("rst_packet")
- {
- Packet* pkt = get_rst_packet( flow );
- REQUIRE( ( pkt != nullptr ) );
-
- SECTION("rst_sent")
- {
- TcpSegmentDescriptor* tcp_seg = new TcpSegmentDescriptor( flow, pkt );
- REQUIRE( ( tcp_seg != nullptr ) );
- client_tracker->set_tcp_event( TcpStreamTracker::TCP_RST_SENT_EVENT );
- tsh->eval( *tcp_seg, *client_tracker );
- CHECK( ( tsh->get_tcp_event() == client_tracker->get_tcp_event() ) );
- delete tcp_seg;
- }
-
- SECTION("rst_recv")
- {
- TcpSegmentDescriptor* tcp_seg = new TcpSegmentDescriptor( flow, pkt );
- REQUIRE( ( tcp_seg != nullptr ) );
- server_tracker->set_tcp_event( TcpStreamTracker::TCP_RST_RECV_EVENT );
- tsh->eval( *tcp_seg, *server_tracker );
- CHECK( ( tsh->get_tcp_event() == server_tracker->get_tcp_event() ) );
- delete tcp_seg;
- }
-
- delete pkt;
- }
-
- delete flow;
- delete tsh;
- delete client_tracker;
- delete server_tracker;
+ // initialization code here
+ Flow* flow = new Flow;
+ TcpStateHandler* tsh = new TcpStateHandler;
+ TcpStreamTracker* client_tracker = new TcpStreamTracker(true);
+ TcpStreamTracker* server_tracker = new TcpStreamTracker(false);
+ TcpEventLogger* tel = new TcpEventLogger;
+
+ GIVEN("a SYN Packet")
+ {
+ Packet* pkt = get_syn_packet(flow);
+ REQUIRE( ( pkt != nullptr ) );
+
+ WHEN("SYN is sent")
+ {
+ TcpSegmentDescriptor* tsd = new TcpSegmentDescriptor(flow, pkt, tel);
+ REQUIRE( ( tsd != nullptr ) );
+ client_tracker->set_tcp_event(TcpStreamTracker::TCP_SYN_SENT_EVENT);
+ tsh->eval(*tsd, *client_tracker);
+ THEN("Event should be TCP_SYN_SENT_EVENT")
+ {
+ CHECK( ( tsh->get_tcp_event() == client_tracker->get_tcp_event() ) );
+ }
+ delete tsd;
+ }
+
+ SECTION("SYN is received")
+ {
+ TcpSegmentDescriptor* tsd = new TcpSegmentDescriptor(flow, pkt, tel);
+ REQUIRE( ( tsd != nullptr ) );
+ server_tracker->set_tcp_event(TcpStreamTracker::TCP_SYN_RECV_EVENT);
+ tsh->eval(*tsd, *server_tracker);
+ CHECK( ( tsh->get_tcp_event() == server_tracker->get_tcp_event() ) );
+ delete tsd;
+ }
+
+ delete pkt;
+ }
+ SECTION("syn_ack_packet")
+ {
+ Packet* pkt = get_syn_ack_packet(flow);
+ REQUIRE( ( pkt != nullptr ) );
+
+ SECTION("syn_ack_sent")
+ {
+ TcpSegmentDescriptor* tsd = new TcpSegmentDescriptor(flow, pkt, tel);
+ REQUIRE( ( tsd != nullptr ) );
+ client_tracker->set_tcp_event(TcpStreamTracker::TCP_SYN_ACK_SENT_EVENT);
+ tsh->eval(*tsd, *client_tracker);
+ CHECK( ( tsh->get_tcp_event() == client_tracker->get_tcp_event() ) );
+ delete tsd;
+ }
+
+ SECTION("syn_ack_recv")
+ {
+ TcpSegmentDescriptor* tsd = new TcpSegmentDescriptor(flow, pkt, tel);
+ REQUIRE( ( tsd != nullptr ) );
+ server_tracker->set_tcp_event(TcpStreamTracker::TCP_SYN_ACK_RECV_EVENT);
+ tsh->eval(*tsd, *server_tracker);
+ CHECK( ( tsh->get_tcp_event() == server_tracker->get_tcp_event() ) );
+ delete tsd;
+ }
+
+ delete pkt;
+ }
+
+ SECTION("ack_packet")
+ {
+ Packet* pkt = get_ack_packet(flow);
+ REQUIRE( ( pkt != nullptr ) );
+
+ SECTION("ack_sent")
+ {
+ TcpSegmentDescriptor* tsd = new TcpSegmentDescriptor(flow, pkt, tel);
+ REQUIRE( ( tsd != nullptr ) );
+ client_tracker->set_tcp_event(TcpStreamTracker::TCP_ACK_SENT_EVENT);
+ tsh->eval(*tsd, *client_tracker);
+ CHECK( ( tsh->get_tcp_event() == client_tracker->get_tcp_event() ) );
+ delete tsd;
+ }
+
+ SECTION("ack_recv")
+ {
+ TcpSegmentDescriptor* tsd = new TcpSegmentDescriptor(flow, pkt, tel);
+ REQUIRE( ( tsd != nullptr ) );
+ server_tracker->set_tcp_event(TcpStreamTracker::TCP_ACK_RECV_EVENT);
+ tsh->eval(*tsd, *server_tracker);
+ CHECK( ( tsh->get_tcp_event() == server_tracker->get_tcp_event() ) );
+ delete tsd;
+ }
+
+ delete pkt;
+ }
+
+ SECTION("data_seg_packet")
+ {
+ Packet* pkt = get_data_packet(flow);
+ REQUIRE( ( pkt != nullptr ) );
+
+ SECTION("data_seg_sent")
+ {
+ TcpSegmentDescriptor* tsd = new TcpSegmentDescriptor(flow, pkt, tel);
+ REQUIRE( ( tsd != nullptr ) );
+ client_tracker->set_tcp_event(TcpStreamTracker::TCP_DATA_SEG_SENT_EVENT);
+ tsh->eval(*tsd, *client_tracker);
+ CHECK( ( tsh->get_tcp_event() == client_tracker->get_tcp_event() ) );
+ delete tsd;
+ }
+
+ SECTION("data_seg_recv")
+ {
+ TcpSegmentDescriptor* tsd = new TcpSegmentDescriptor(flow, pkt, tel);
+ REQUIRE( ( tsd != nullptr ) );
+ server_tracker->set_tcp_event(TcpStreamTracker::TCP_DATA_SEG_RECV_EVENT);
+ tsh->eval(*tsd, *server_tracker);
+ CHECK( ( tsh->get_tcp_event() == server_tracker->get_tcp_event() ) );
+ delete tsd;
+ }
+
+ delete pkt;
+ }
+
+ SECTION("fin_packet")
+ {
+ Packet* pkt = get_fin_packet(flow);
+ REQUIRE( ( pkt != nullptr ) );
+
+ SECTION("fin_sent")
+ {
+ TcpSegmentDescriptor* tsd = new TcpSegmentDescriptor(flow, pkt, tel);
+ REQUIRE( ( tsd != nullptr ) );
+ client_tracker->set_tcp_event(TcpStreamTracker::TCP_FIN_SENT_EVENT);
+ tsh->eval(*tsd, *client_tracker);
+ CHECK( ( tsh->get_tcp_event() == client_tracker->get_tcp_event() ) );
+ delete tsd;
+ }
+
+ SECTION("fin_recv")
+ {
+ TcpSegmentDescriptor* tsd = new TcpSegmentDescriptor(flow, pkt, tel);
+ REQUIRE( ( tsd != nullptr ) );
+ server_tracker->set_tcp_event(TcpStreamTracker::TCP_FIN_RECV_EVENT);
+ tsh->eval(*tsd, *server_tracker);
+ CHECK( ( tsh->get_tcp_event() == server_tracker->get_tcp_event() ) );
+ delete tsd;
+ }
+
+ delete pkt;
+ }
+
+ SECTION("rst_packet")
+ {
+ Packet* pkt = get_rst_packet(flow);
+ REQUIRE( ( pkt != nullptr ) );
+
+ SECTION("rst_sent")
+ {
+ TcpSegmentDescriptor* tsd = new TcpSegmentDescriptor(flow, pkt, tel);
+ REQUIRE( ( tsd != nullptr ) );
+ client_tracker->set_tcp_event(TcpStreamTracker::TCP_RST_SENT_EVENT);
+ tsh->eval(*tsd, *client_tracker);
+ CHECK( ( tsh->get_tcp_event() == client_tracker->get_tcp_event() ) );
+ delete tsd;
+ }
+
+ SECTION("rst_recv")
+ {
+ TcpSegmentDescriptor* tsd = new TcpSegmentDescriptor(flow, pkt, tel);
+ REQUIRE( ( tsd != nullptr ) );
+ server_tracker->set_tcp_event(TcpStreamTracker::TCP_RST_RECV_EVENT);
+ tsh->eval(*tsd, *server_tracker);
+ CHECK( ( tsh->get_tcp_event() == server_tracker->get_tcp_event() ) );
+ delete tsd;
+ }
+
+ delete pkt;
+ }
+
+ delete flow;
+ delete tsh;
+ delete client_tracker;
+ delete server_tracker;
}
#endif
+
#include "tcp_segment_descriptor.h"
#include "tcp_stream_tracker.h"
+class TcpStateMachine;
+
class TcpStateHandler
{
-
public:
- TcpStateHandler();
+ TcpStateHandler(TcpStreamTracker::TcpStates, TcpStateMachine&);
+ TcpStateHandler(void);
virtual ~TcpStateHandler();
- virtual void eval(TcpSegmentDescriptor&, TcpStreamTracker&);
+ virtual bool eval(TcpSegmentDescriptor&, TcpStreamTracker&);
- TcpStreamTracker::TcpEvents get_tcp_event() const {
+ TcpStreamTracker::TcpEvents get_tcp_event() const
+ {
return tcp_event;
}
+ TcpStreamTracker::TcpStates get_tcp_state() const
+ {
+ return tcp_state;
+ }
+
+ void set_tcp_state(TcpStreamTracker::TcpStates tcp_state)
+ {
+ this->tcp_state = tcp_state;
+ }
+
+ void set_tcp_event(TcpStreamTracker::TcpEvents tcp_event)
+ {
+ this->tcp_event = tcp_event;
+ }
+
+ const TcpStateMachine* get_tsm() const
+ {
+ return tsm;
+ }
+
+ void set_tsm(const TcpStateMachine* tsm)
+ {
+ this->tsm = tsm;
+ }
+
protected:
- virtual void syn_sent(TcpSegmentDescriptor&, TcpStreamTracker&);
- virtual void syn_recv(TcpSegmentDescriptor&, TcpStreamTracker&);
- virtual void syn_ack_sent(TcpSegmentDescriptor&, TcpStreamTracker&);
- virtual void syn_ack_recv(TcpSegmentDescriptor&, TcpStreamTracker&);
- virtual void ack_sent(TcpSegmentDescriptor&, TcpStreamTracker&);
- virtual void ack_recv(TcpSegmentDescriptor&, TcpStreamTracker&);
- virtual void data_seg_sent(TcpSegmentDescriptor&, TcpStreamTracker&);
- virtual void data_seg_recv(TcpSegmentDescriptor&, TcpStreamTracker&);
- virtual void fin_sent(TcpSegmentDescriptor&, TcpStreamTracker&);
- virtual void fin_recv(TcpSegmentDescriptor&, TcpStreamTracker&);
- virtual void rst_sent(TcpSegmentDescriptor&, TcpStreamTracker&);
- virtual void rst_recv(TcpSegmentDescriptor&, TcpStreamTracker&);
-
- void default_state_action( TcpSegmentDescriptor*, TcpStreamTracker*, const char* );
+ virtual bool syn_sent(TcpSegmentDescriptor&, TcpStreamTracker&);
+ virtual bool syn_recv(TcpSegmentDescriptor&, TcpStreamTracker&);
+ virtual bool syn_ack_sent(TcpSegmentDescriptor&, TcpStreamTracker&);
+ virtual bool syn_ack_recv(TcpSegmentDescriptor&, TcpStreamTracker&);
+ virtual bool ack_sent(TcpSegmentDescriptor&, TcpStreamTracker&);
+ virtual bool ack_recv(TcpSegmentDescriptor&, TcpStreamTracker&);
+ virtual bool data_seg_sent(TcpSegmentDescriptor&, TcpStreamTracker&);
+ virtual bool data_seg_recv(TcpSegmentDescriptor&, TcpStreamTracker&);
+ virtual bool fin_sent(TcpSegmentDescriptor&, TcpStreamTracker&);
+ virtual bool fin_recv(TcpSegmentDescriptor&, TcpStreamTracker&);
+ virtual bool rst_sent(TcpSegmentDescriptor&, TcpStreamTracker&);
+ virtual bool rst_recv(TcpSegmentDescriptor&, TcpStreamTracker&);
+
+ bool default_state_action(TcpSegmentDescriptor&, TcpStreamTracker&, const char*);
+ const TcpStateMachine* tsm;
+ TcpStreamTracker::TcpStates tcp_state;
TcpStreamTracker::TcpEvents tcp_event;
};
#endif
+
// tcp_state_machine.cc author davis mcpherson <davmcphe@@cisco.com>
// Created on: Jul 29, 2015
+#include "tcp_stream_tracker.h"
#include "tcp_state_machine.h"
-const char* tcp_state_names[] =
-{ "TCP_LISTEN", "TCP_SYN_SENT", "TCP_SYN_RECV", "TCP_ESTABLISHED","TCP_FIN_WAIT1",
- "TCP_FIN_WAIT2", "TCP_CLOSE_WAIT", "TCP_CLOSING", "TCP_LAST_ACK",
- "TCP_TIME_WAIT", "TCP_CLOSED"
-};
-
-const char *tcp_event_names[] = { "TCP_SYN_SENT_EVENT", "TCP_SYN_RECV_EVENT",
- "TCP_SYN_ACK_SENT_EVENT", "TCP_SYN_ACK_RECV_EVENT", "TCP_ACK_SENT_EVENT",
- "TCP_ACK_RECV_EVENT", "TCP_DATA_SEG_SENT_EVENT", "TCP_DATA_SEG_RECV_EVENT",
- "TCP_FIN_SENT_EVENT", "TCP_FIN_RECV_EVENT", "TCP_RST_SENT_EVENT", "TCP_RST_RECV_EVENT" };
-
+TcpStateMachine::TcpStateMachine(void)
+{
+ // register a default handler for each state...
+ for ( TcpStreamTracker::TcpStates state = TcpStreamTracker::TCP_LISTEN; state <
+ TcpStreamTracker::TCP_MAX_STATES; state++ )
+ {
+ tcp_state_handlers[ state ] = nullptr;
+ new TcpStateHandler(state, *this);
+ }
+}
-TcpStateMachine::~TcpStateMachine()
+TcpStateMachine::~TcpStateMachine(void)
{
// TODO Auto-generated destructor stub
}
-TcpStateMachine::TcpStateMachine()
+
+void TcpStateMachine::register_state_handler(TcpStreamTracker::TcpStates state,
+ TcpStateHandler& handler)
{
- // TODO Auto-generated constructor stub
+ if ( tcp_state_handlers[ state ] != nullptr )
+ delete tcp_state_handlers[ state ];
+ tcp_state_handlers[ state ] = &handler;
}
-void TcpStateMachine::eval( TcpSegmentDescriptor &tcp_seg, TcpStreamTracker &tracker )
+bool TcpStateMachine::eval(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
{
- tracker.set_tcp_event( tcp_seg, tracker.is_client_tracker( ) );
- tcp_state_handlers[ tracker.get_tcp_state( ) ]->eval( tcp_seg, tracker );
+ tracker.set_tcp_event(tsd);
+ return tcp_state_handlers[ tracker.get_tcp_state( ) ]->eval(tsd, tracker);
}
+
#include "tcp_stream_tracker.h"
#include "tcp_segment_descriptor.h"
-extern const char* tcp_state_names[];
-extern const char* tcp_event_names[];
-
class TcpStateMachine
{
public:
- virtual ~TcpStateMachine();
+ TcpStateMachine(void);
+ virtual ~TcpStateMachine(void);
- virtual void eval(TcpSegmentDescriptor&, TcpStreamTracker&);
+ virtual void register_state_handler(TcpStreamTracker::TcpStates, TcpStateHandler&);
+ virtual bool eval(TcpSegmentDescriptor&, TcpStreamTracker&);
private:
- TcpStateMachine();
- TcpStateHandler *tcp_state_handlers[ TcpStreamTracker::TCP_MAX_STATES ];
+ TcpStateHandler* tcp_state_handlers[ TcpStreamTracker::TCP_MAX_STATES ];
};
#endif
+
// tcp_stream_tracker.cpp author davis mcpherson <davmcphe@@cisco.com>
// Created on: Jun 24, 2015
-#include "tcp_stream_tracker.h"
+#include "protocols/tcp_options.h"
+#include "protocols/tcp.h"
+#include "protocols/eth.h"
+#include "profiler/profiler.h"
+
#include "stream/stream.h"
+#include "tcp_stream_tracker.h"
+
+const char* tcp_state_names[] =
+{ "TCP_LISTEN", "TCP_SYN_SENT", "TCP_SYN_RECV", "TCP_ESTABLISHED","TCP_FIN_WAIT1",
+ "TCP_FIN_WAIT2", "TCP_CLOSE_WAIT", "TCP_CLOSING", "TCP_LAST_ACK",
+ "TCP_TIME_WAIT", "TCP_CLOSED", "TCP_STATE_NONE",};
-TcpStreamTracker::TcpStreamTracker( bool client ) :
- client_tracker( client )
+const char* tcp_event_names[] = { "TCP_SYN_SENT_EVENT", "TCP_SYN_RECV_EVENT",
+ "TCP_SYN_ACK_SENT_EVENT", "TCP_SYN_ACK_RECV_EVENT",
+ "TCP_ACK_SENT_EVENT",
+ "TCP_ACK_RECV_EVENT", "TCP_DATA_SEG_SENT_EVENT",
+ "TCP_DATA_SEG_RECV_EVENT",
+ "TCP_FIN_SENT_EVENT", "TCP_FIN_RECV_EVENT", "TCP_RST_SENT_EVENT",
+ "TCP_RST_RECV_EVENT" };
+
+TcpStreamTracker::TcpStreamTracker(bool client) :
+ client_tracker(client), require_3whs(false), snd_una(0), snd_nxt(0), snd_wnd(0), snd_up(0),
+ snd_wl1(0), snd_wl2(0), iss(0), rcv_nxt(0), rcv_wnd(0), rcv_up(0), irs(0),
+ ts_last_packet(0), ts_last(0), wscale(0), mss(0), flags(0)
{
- tcp_state = ( client ) ? TCP_CLOSED : TCP_LISTEN;
+ memset(mac_addr, '0', sizeof(mac_addr));
+ tcp_state = TCP_STATE_NONE;
tcp_event = TCP_MAX_EVENTS;
}
// TODO Auto-generated destructor stub
}
-void TcpStreamTracker::set_tcp_event( TcpSegmentDescriptor &tcp_seg, bool client )
+void TcpStreamTracker::set_tcp_event(TcpSegmentDescriptor& tsd)
{
- bool talker;
+ bool talker;
+ const tcp::TCPHdr* tcph = tsd.get_tcph();
- if( tcp_seg.get_direction( ) == FROM_CLIENT )
- talker = ( client ) ? true : false;
+ if ( tsd.get_pkt()->packet_flags & PKT_FROM_CLIENT )
+ talker = ( client_tracker ) ? true : false;
else
- talker = ( client ) ? false : true;
+ talker = ( client_tracker ) ? false : true;
- if( talker )
+ if ( talker )
{
- if( tcp_seg.get_tcph()->is_syn_only() )
+ if ( tcph->is_syn_only() )
tcp_event = TCP_SYN_SENT_EVENT;
- else if( tcp_seg.get_tcph()->is_syn_ack() )
+ else if ( tcph->is_syn_ack() )
tcp_event = TCP_SYN_ACK_SENT_EVENT;
- else if( tcp_seg.get_tcph()->is_ack() )
+ else if ( tcph->is_ack() || tcph->is_psh() )
{
- if( tcp_seg.get_data_len() > 0 )
+ if ( tsd.get_data_len() > 0 )
tcp_event = TCP_DATA_SEG_SENT_EVENT;
else
tcp_event = TCP_ACK_SENT_EVENT;
}
- else if( tcp_seg.get_tcph()->is_rst() )
+ else if ( tcph->is_rst() )
tcp_event = TCP_RST_SENT_EVENT;
- else if( tcp_seg.get_tcph()->is_fin( ) )
+ else if ( tcph->is_fin( ) )
tcp_event = TCP_FIN_SENT_EVENT;
+// else if( tsd.get_data_len() > 0 ) // FIXIT - No flags set, how do we handle this?
+// tcp_event = TCP_DATA_SEG_SENT_EVENT;
else
- tcp_event = TCP_MAX_EVENTS;
+ tcp_event = TCP_ACK_SENT_EVENT;
}
else // server is listening events
{
- if( tcp_seg.get_tcph()->is_syn_only() )
- tcp_event = TCP_SYN_RECV_EVENT;
- else if( tcp_seg.get_tcph()->is_syn_ack() )
- tcp_event = TCP_SYN_ACK_RECV_EVENT;
- else if( tcp_seg.get_tcph()->is_ack() )
- {
- if( tcp_seg.get_data_len() > 0 )
- tcp_event = TCP_DATA_SEG_RECV_EVENT;
- else
- tcp_event = TCP_ACK_RECV_EVENT;
- }
- else if( tcp_seg.get_tcph()->is_rst() )
- tcp_event = TCP_RST_RECV_EVENT;
- else if( tcp_seg.get_tcph()->is_fin( ) )
- tcp_event = TCP_FIN_RECV_EVENT;
+ if ( tcph->is_syn_only() )
+ tcp_event = TCP_SYN_RECV_EVENT;
+ else if ( tcph->is_syn_ack() )
+ tcp_event = TCP_SYN_ACK_RECV_EVENT;
+ else if ( tcph->is_ack() || tcph->is_psh() )
+ {
+ if ( tsd.get_data_len() > 0 )
+ tcp_event = TCP_DATA_SEG_RECV_EVENT;
+ else
+ tcp_event = TCP_ACK_RECV_EVENT;
+ }
+ else if ( tcph->is_rst() )
+ tcp_event = TCP_RST_RECV_EVENT;
+ else if ( tcph->is_fin( ) )
+ tcp_event = TCP_FIN_RECV_EVENT;
+// else if( tsd.get_data_len() > 0 ) // FIXIT - No flags set, how do we handle this?
+// tcp_event = TCP_DATA_SEG_RECV_EVENT;
+ else
+ tcp_event = TCP_ACK_RECV_EVENT;
}
}
+
+// Use a for loop and byte comparison, which has proven to be faster on pipelined architectures
+// compared to a memcmp (setup for memcmp is slow). Not using a 4 byte and 2 byte long because
+// there is no guarantee of memory alignment (and thus performance issues similar to memcmp).
+bool TcpStreamTracker::compare_mac_addresses(const uint8_t eth_addr[])
+{
+ for ( int i = 0; i < 6; ++i )
+ if ( mac_addr[i] != eth_addr[i] )
+ return false;
+
+ return true;
+}
+
+void TcpStreamTracker::cache_mac_address(TcpSegmentDescriptor& tsd, uint8_t direction)
+{
+ int i;
+
+ /* Not Ethernet based, nothing to do */
+ if ( !( tsd.get_pkt()->proto_bits & PROTO_BIT__ETH ) )
+ return;
+
+ // if flag is set, guaranteed to have an eth layer
+ const eth::EtherHdr* eh = layer::get_eth_layer(tsd.get_pkt() );
+
+ if ( direction == FROM_CLIENT )
+ {
+ if ( client_tracker )
+ for ( i = 0; i < 6; i++ )
+ mac_addr[i] = eh->ether_src[i];
+ else
+ for ( i = 0; i < 6; i++ )
+ mac_addr[i] = eh->ether_dst[i];
+ }
+ else
+ {
+ if ( client_tracker )
+ for ( i = 0; i < 6; i++ )
+ mac_addr[i] = eh->ether_dst[i];
+ else
+ for ( i = 0; i < 6; i++ )
+ mac_addr[i] = eh->ether_src[i];
+ }
+}
+
#include "tcp_segment_descriptor.h"
+extern const char* tcp_state_names[];
+extern const char* tcp_event_names[];
+
class TcpStreamTracker
{
public:
enum TcpStates
- {
- TCP_LISTEN,
- TCP_SYN_SENT,
- TCP_SYN_RECV,
- TCP_ESTABLISHED,
- TCP_FIN_WAIT1,
- TCP_FIN_WAIT2,
- TCP_CLOSE_WAIT,
- TCP_CLOSING,
- TCP_LAST_ACK,
- TCP_TIME_WAIT,
- TCP_CLOSED,
- TCP_MAX_STATES
- };
-
- enum TcpEvents
- {
- TCP_SYN_SENT_EVENT,
- TCP_SYN_RECV_EVENT,
- TCP_SYN_ACK_SENT_EVENT,
- TCP_SYN_ACK_RECV_EVENT,
- TCP_ACK_SENT_EVENT,
- TCP_ACK_RECV_EVENT,
- TCP_DATA_SEG_SENT_EVENT,
- TCP_DATA_SEG_RECV_EVENT,
- TCP_FIN_SENT_EVENT,
- TCP_FIN_RECV_EVENT,
- TCP_RST_SENT_EVENT,
- TCP_RST_RECV_EVENT,
- TCP_MAX_EVENTS
- };
-
- TcpStreamTracker( bool );
+ {
+ TCP_LISTEN,
+ TCP_SYN_SENT,
+ TCP_SYN_RECV,
+ TCP_ESTABLISHED,
+ TCP_FIN_WAIT1,
+ TCP_FIN_WAIT2,
+ TCP_CLOSE_WAIT,
+ TCP_CLOSING,
+ TCP_LAST_ACK,
+ TCP_TIME_WAIT,
+ TCP_CLOSED,
+ TCP_STATE_NONE,
+ TCP_MAX_STATES
+ };
+
+ enum TcpEvents
+ {
+ TCP_SYN_SENT_EVENT,
+ TCP_SYN_RECV_EVENT,
+ TCP_SYN_ACK_SENT_EVENT,
+ TCP_SYN_ACK_RECV_EVENT,
+ TCP_ACK_SENT_EVENT,
+ TCP_ACK_RECV_EVENT,
+ TCP_DATA_SEG_SENT_EVENT,
+ TCP_DATA_SEG_RECV_EVENT,
+ TCP_FIN_SENT_EVENT,
+ TCP_FIN_RECV_EVENT,
+ TCP_RST_SENT_EVENT,
+ TCP_RST_RECV_EVENT,
+ TCP_MAX_EVENTS
+ };
+
+ TcpStreamTracker(bool);
virtual ~TcpStreamTracker();
- bool is_client_tracker() const {
+ bool is_client_tracker() const
+ {
return client_tracker;
}
- TcpStates get_tcp_state() const {
+ bool is_3whs_required() const
+ {
+ return require_3whs;
+ }
+
+ void set_require_3whs(bool require3_whs)
+ {
+ this->require_3whs = require3_whs;
+ }
+
+ TcpStates get_tcp_state() const
+ {
return tcp_state;
}
- void set_tcp_state(TcpStates tcp_state) {
+ void set_tcp_state(TcpStates tcp_state)
+ {
this->tcp_state = tcp_state;
}
- TcpEvents get_tcp_event() const {
+ TcpEvents get_tcp_event() const
+ {
return tcp_event;
}
- void set_tcp_event( TcpSegmentDescriptor &tcp_seg, bool client );
+ void set_tcp_event(TcpSegmentDescriptor& tsd);
- void set_tcp_event(TcpEvents tcp_event) {
+ void set_tcp_event(TcpEvents tcp_event)
+ {
this->tcp_event = tcp_event;
}
- uint32_t get_irs() const {
- return irs;
- }
-
- void set_irs(uint32_t irs) {
- this->irs = irs;
- }
-
- uint32_t get_iss() const {
- return iss;
+ uint32_t get_rcv_nxt() const
+ {
+ return rcv_nxt;
}
- void set_iss(uint32_t iss) {
- this->iss = iss;
+ void set_rcv_nxt(uint32_t rcv_nxt)
+ {
+ this->rcv_nxt = rcv_nxt;
}
- uint32_t get_rcv_nxt() const {
- return rcv_nxt;
+ uint32_t get_rcv_wnd() const
+ {
+ return rcv_wnd;
}
- void set_rcv_nxt(uint32_t rcv_nxt) {
- this->rcv_nxt = rcv_nxt;
+ void set_rcv_wnd(uint32_t rcv_wnd)
+ {
+ this->rcv_wnd = rcv_wnd;
}
- uint16_t get_rcv_up() const {
+ uint16_t get_rcv_up() const
+ {
return rcv_up;
}
- void set_rcv_up(uint16_t rcv_up) {
+ void set_rcv_up(uint16_t rcv_up)
+ {
this->rcv_up = rcv_up;
}
- uint16_t get_rcv_wnd() const {
- return rcv_wnd;
+ uint32_t get_irs() const
+ {
+ return irs;
}
- void set_rcv_wnd(uint16_t rcv_wnd) {
- this->rcv_wnd = rcv_wnd;
+ void set_irs(uint32_t irs)
+ {
+ this->irs = irs;
}
- uint32_t get_snd_nxt() const {
- return snd_nxt;
+ uint32_t get_snd_una() const
+ {
+ return snd_una;
}
- void set_snd_nxt(uint32_t snd_nxt) {
- this->snd_nxt = snd_nxt;
+ void set_snd_una(uint32_t snd_una)
+ {
+ this->snd_una = snd_una;
}
- uint32_t get_snd_una() const {
- return snd_una;
+ uint32_t get_snd_nxt() const
+ {
+ return snd_nxt;
}
- void set_snd_una(uint32_t snd_una) {
- this->snd_una = snd_una;
+ void set_snd_nxt(uint32_t snd_nxt)
+ {
+ this->snd_nxt = snd_nxt;
}
- uint16_t get_snd_up() const {
+ uint16_t get_snd_up() const
+ {
return snd_up;
}
- void set_snd_up(uint16_t snd_up) {
+ void set_snd_up(uint16_t snd_up)
+ {
this->snd_up = snd_up;
}
- uint32_t get_snd_wl1() const {
+ uint32_t get_snd_wl1() const
+ {
return snd_wl1;
}
- void set_snd_wl1(uint32_t snd_wl1) {
+ void set_snd_wl1(uint32_t snd_wl1)
+ {
this->snd_wl1 = snd_wl1;
}
- uint32_t get_snd_wl2() const {
+ uint32_t get_snd_wl2() const
+ {
return snd_wl2;
}
- void set_snd_wl2(uint32_t snd_wl2) {
+ void set_snd_wl2(uint32_t snd_wl2)
+ {
this->snd_wl2 = snd_wl2;
}
- uint16_t get_snd_wnd() const {
+ uint32_t get_snd_wnd() const
+ {
return snd_wnd;
}
- void set_snd_wnd(uint16_t snd_wnd) {
+ void set_snd_wnd(uint32_t snd_wnd)
+ {
this->snd_wnd = snd_wnd;
}
- uint32_t get_ts_last_packet() const {
+ uint32_t get_iss() const
+ {
+ return iss;
+ }
+
+ void set_iss(uint32_t iss)
+ {
+ this->iss = iss;
+ }
+
+ uint32_t get_ts_last_packet() const
+ {
return ts_last_packet;
}
- void set_ts_last_packet(uint32_t ts_last_packet) {
+ void set_ts_last_packet(uint32_t ts_last_packet)
+ {
this->ts_last_packet = ts_last_packet;
}
+ bool is_ack_valid(uint32_t cur)
+ {
+ /* If we haven't seen anything, ie, low & high are 0, return true */
+ if ( ( snd_una == 0 ) && ( snd_una == snd_nxt ) )
+ return 1;
+
+ return ( SEQ_GEQ(cur, snd_una) && SEQ_LEQ(cur, snd_nxt) );
+ }
+
+ // ack number must ack syn
+ bool is_rst_valid_in_syn_sent(TcpSegmentDescriptor& tsd)
+ {
+ return tsd.get_ack() == snd_una;
+ }
+
+ void cache_mac_address(TcpSegmentDescriptor& tsd, uint8_t direction);
+ bool compare_mac_addresses(const uint8_t eth_addr[]);
+
protected:
+ bool client_tracker;
+ bool require_3whs;
+
uint32_t snd_una; // SND.UNA - send unacknowledged
uint32_t snd_nxt; // SND.NXT - send next
- uint16_t snd_wnd; // SND.WND - send window
+ uint32_t snd_wnd; // SND.WND - send window
uint16_t snd_up; // SND.UP - send urgent pointer
uint32_t snd_wl1; // SND.WL1 - segment sequence number used for last window update
uint32_t snd_wl2; // SND.WL2 - segment acknowledgment number used for last window update
uint32_t iss; // ISS - initial send sequence number
uint32_t rcv_nxt; // RCV.NXT - receive next
- uint16_t rcv_wnd; // RCV.WND - receive window
+ uint32_t rcv_wnd; // RCV.WND - receive window
uint16_t rcv_up; // RCV.UP - receive urgent pointer
uint32_t irs; // IRS - initial receive sequence number
uint32_t ts_last_packet; // timestamp of last packet we got
- bool client_tracker;
+ // FIXIT - make this protected
+public:
+ uint32_t ts_last; /* last timestamp (for PAWS) */
+ uint16_t wscale; /* window scale setting */
+ uint16_t mss; /* max segment size */
+
+ uint8_t mac_addr[6];
+ uint8_t flags; /* bitmap flags (TF_xxx) */
+
+protected:
TcpStates tcp_state;
TcpEvents tcp_event;
};
+inline TcpStreamTracker::TcpStates& operator++(TcpStreamTracker::TcpStates& state, int) // <---
+ // note --
+ // must be
+ // a reference
+{
+ const int i = static_cast<int>(state);
+ state = static_cast<TcpStreamTracker::TcpStates>((i + 1) % ( TcpStreamTracker::TCP_MAX_EVENTS +
+ 1 ) );
+ return state;
+}
+
#endif
+
tcp_module.cc
tcp_module.h
tcp_defs.h
- tcp_events.h
+ tcp_event_logger.h
+ tcp_event_logger.cc
+ tcp_stream_config.h
+ tcp_stream_config.cc
tcp_normalizer.h
tcp_normalizer.cc
tcp_normalizers.h
tcp_normalizers.cc
- tcp_segment.h
- tcp_segment.cc
+ tcp_segment_node.h
+ tcp_segment_node.cc
tcp_reassembler.h
tcp_reassembler.cc
tcp_reassemblers.h
tcp_reassemblers.cc
+ tcp_tracker.cc
+ tcp_tracker.h
tcp_session.cc
tcp_session.h
- tcp_closed_state.cc
- tcp_listen_state.cc
- tcp_syn_sent_state.cc
- tcp_syn_recv_state.cc
+ tcp_state_closed.cc
+ tcp_state_close_wait.cc
+ tcp_state_closing.cc
+ tcp_state_established.cc
+ tcp_state_fin_wait1.cc
+ tcp_state_fin_wait2.cc
+ tcp_state_last_ack.cc
+ tcp_state_listen.cc
+ tcp_state_none.cc
+ tcp_state_syn_recv.cc
+ tcp_state_syn_sent.cc
+ tcp_state_time_wait.cc
+ tcp_state_closed.h
+ tcp_state_close_wait.h
+ tcp_state_closing.h
+ tcp_state_established.h
+ tcp_state_fin_wait1.h
+ tcp_state_fin_wait2.h
+ tcp_state_last_ack.h
+ tcp_state_listen.h
+ tcp_state_none.h
+ tcp_state_syn_recv.h
+ tcp_state_syn_sent.h
+ tcp_state_time_wait.h
ips_stream_reassemble.cc
ips_stream_size.cc
)
tcp_module.h \
tcp_debug_trace.h \
tcp_defs.h \
-tcp_events.h \
+tcp_event_logger.h \
+tcp_event_logger.cc \
+tcp_stream_config.h \
+tcp_stream_config.cc \
tcp_normalizer.h \
tcp_normalizer.cc \
tcp_normalizers.h \
tcp_normalizers.cc \
-tcp_segment.h \
-tcp_segment.cc \
+tcp_segment_node.h \
+tcp_segment_node.cc \
tcp_reassembler.h \
tcp_reassembler.cc \
tcp_reassemblers.h \
tcp_reassemblers.cc \
+tcp_tracker.cc \
+tcp_tracker.h \
tcp_session.cc \
tcp_session.h \
-tcp_closed_state.h \
-tcp_closed_state.cc \
-tcp_listen_state.cc \
-tcp_listen_state.h \
-tcp_syn_sent_state.cc \
-tcp_syn_sent_state.h \
-tcp_syn_recv_state.cc \
-tcp_syn_recv_state.h \
+tcp_state_closed.cc \
+tcp_state_close_wait.cc \
+tcp_state_closing.cc \
+tcp_state_established.cc \
+tcp_state_fin_wait1.cc \
+tcp_state_fin_wait2.cc \
+tcp_state_last_ack.cc \
+tcp_state_listen.cc \
+tcp_state_none.cc \
+tcp_state_syn_recv.cc \
+tcp_state_syn_sent.cc \
+tcp_state_time_wait.cc \
+tcp_state_closed.h \
+tcp_state_close_wait.h \
+tcp_state_closing.h \
+tcp_state_established.h \
+tcp_state_fin_wait1.h \
+tcp_state_fin_wait2.h \
+tcp_state_last_ack.h \
+tcp_state_listen.h \
+tcp_state_none.h \
+tcp_state_syn_recv.h \
+tcp_state_syn_sent.h \
+tcp_state_time_wait.h \
ips_stream_reassemble.cc \
ips_stream_size.cc
{
if ( srod.direction & SSN_DIR_FROM_SERVER )
{
- tcpssn->server.flush_policy = STREAM_FLPOLICY_IGNORE;
+ tcpssn->server->flush_policy = STREAM_FLPOLICY_IGNORE;
stream.set_splitter(lwssn, true);
}
if ( srod.direction & SSN_DIR_FROM_CLIENT )
{
- tcpssn->client.flush_policy = STREAM_FLPOLICY_IGNORE;
+ tcpssn->client->flush_policy = STREAM_FLPOLICY_IGNORE;
stream.set_splitter(lwssn, false);
}
}
// FIXIT-M PAF need to check for ips / on-data
if ( srod.direction & SSN_DIR_FROM_SERVER )
{
- tcpssn->server.flush_policy = STREAM_FLPOLICY_ON_ACK;
+ tcpssn->server->flush_policy = STREAM_FLPOLICY_ON_ACK;
stream.set_splitter(lwssn, true, new AtomSplitter(true));
}
if ( srod.direction & SSN_DIR_FROM_CLIENT )
{
- tcpssn->client.flush_policy = STREAM_FLPOLICY_ON_ACK;
+ tcpssn->client->flush_policy = STREAM_FLPOLICY_ON_ACK;
stream.set_splitter(lwssn, false, new AtomSplitter(false));
}
}
}
}
-
if (srod.alert)
return DETECTION_OPTION_MATCH;
{
// initialization code here
REQUIRE( ( ips_stream_reassemble->api_version == ((BASE_API_VERSION << 16) | 0) ) );
- REQUIRE( ( strcmp( ips_stream_reassemble->name, s_name ) == 0 ) );
- ReassembleModule* reassembler = ( ReassembleModule* ) ips_stream_reassemble->mod_ctor();
+ REQUIRE( ( strcmp(ips_stream_reassemble->name, s_name) == 0 ) );
+ ReassembleModule* reassembler = ( ReassembleModule* )ips_stream_reassemble->mod_ctor();
REQUIRE( ( reassembler != nullptr ) );
Flow* flow = new Flow;
- Packet* pkt = get_syn_packet( flow );
- pkt->flow->session = new TcpSession( flow );
- Cursor cursor( pkt );
+ Packet* pkt = get_syn_packet(flow);
+ pkt->flow->session = new TcpSession(flow);
+ Cursor cursor(pkt);
SECTION("reassembler initialization")
{
- bool status = reassembler->begin( nullptr, 0, snort_conf );
- CHECK( status );
+ bool status = reassembler->begin(nullptr, 0, snort_conf);
+ CHECK(status);
CHECK( ( reassembler->srod.enable == 0 ) );
CHECK( ( reassembler->srod.direction == 0 ) );
CHECK( ( reassembler->srod.alert == 1 ) );
SECTION("eval enable off")
{
reassembler->srod.direction = SSN_DIR_FROM_SERVER;
- IpsOption* ropt = reassemble_api.ctor( reassembler, nullptr );
- int rc = ropt->eval( cursor, pkt );
+ IpsOption* ropt = reassemble_api.ctor(reassembler, nullptr);
+ int rc = ropt->eval(cursor, pkt);
CHECK( ( rc == DETECTION_OPTION_MATCH ) );
- StreamSplitter* ss = stream.get_splitter( flow, true );
+ StreamSplitter* ss = stream.get_splitter(flow, true);
CHECK( ( ss != nullptr ) );
CHECK( ( !ss->is_paf() ) );
- CHECK( ( ( ( TcpSession* ) pkt->flow->session)->server.flush_policy
- == STREAM_FLPOLICY_IGNORE ) );
+ CHECK( ( ( ( TcpSession* )pkt->flow->session)->server.flush_policy
+ == STREAM_FLPOLICY_IGNORE ) );
}
#endif
-
}
-
#endif
+
uint32_t client_size;
uint32_t server_size;
- if (tcpssn->client.l_nxt_seq > tcpssn->client.isn)
+ if (tcpssn->client->get_snd_nxt() > tcpssn->client->get_iss())
{
/* the normal case... */
- client_size = tcpssn->client.l_nxt_seq - tcpssn->client.isn;
+ client_size = tcpssn->client->get_snd_nxt() - tcpssn->client->get_iss();
}
else
{
/* the seq num wrapping case... */
- client_size = tcpssn->client.isn - tcpssn->client.l_nxt_seq;
+ client_size = tcpssn->client->get_iss() - tcpssn->client->get_snd_nxt();
}
- if (tcpssn->server.l_nxt_seq > tcpssn->server.isn)
+ if (tcpssn->server->get_snd_nxt() > tcpssn->server->get_iss())
{
/* the normal case... */
- server_size = tcpssn->server.l_nxt_seq - tcpssn->server.isn;
+ server_size = tcpssn->server->get_snd_nxt() - tcpssn->server->get_iss();
}
else
{
/* the seq num wrapping case... */
- server_size = tcpssn->server.isn - tcpssn->server.l_nxt_seq;
+ server_size = tcpssn->server->get_iss() - tcpssn->server->get_snd_nxt();
}
int result = DETECTION_OPTION_NO_MATCH;
#include "protocols/packet.h"
#include "tcp_module.h"
-#include "tcp_events.h"
+#include "tcp_event_logger.h"
#include "tcp_normalizer.h"
#include "tcp_reassembler.h"
#include "segment_overlap_editor.h"
-bool SegmentOverlapEditor::is_segment_retransmit( void )
+bool SegmentOverlapEditor::is_segment_retransmit(void)
{
// Don't want to count retransmits as overlaps or do anything
// else with them. Account for retransmits of multiple PDUs
// in one segment.
- if( right->is_retransmit( rdata, rsize, rseq ) )
+ if ( right->is_retransmit(rdata, rsize, rseq) )
{
rdata += right->payload_size;
rsize -= right->payload_size;
left = right;
right = right->next;
- if( rsize == 0 )
+ if ( rsize == 0 )
{
// All data was retransmitted
- session->retransmit_process( tdb->pkt );
+ session->retransmit_process(tsd->get_pkt() );
keep_segment = false;
}
return false;
}
-int SegmentOverlapEditor::eval_left( void )
+int SegmentOverlapEditor::eval_left(void)
{
int rc = STREAM_INSERT_OK;
- if( left )
- rc = insert_left_overlap();
+ if ( left )
+ rc = insert_left_overlap();
return rc;
}
-int SegmentOverlapEditor::eval_right( void )
+int SegmentOverlapEditor::eval_right(void)
{
- while( right && SEQ_LT( right->seq, seq_end ) )
+ while ( right && SEQ_LT(right->seq, seq_end) )
{
trunc_len = 0;
- overlap = ( int ) ( seq_end - right->seq );
+ overlap = ( int )( seq_end - right->seq );
DebugFormat(DEBUG_STREAM_STATE, "right overlap(%d): len: %d right->seq: 0x%X seq: 0x%X\n",
- overlap, len, right->seq, seq);
+ overlap, len, right->seq, seq);
// Treat sequence number overlap as a retransmission, only check right side since
// left side happens rarely
- session->retransmit_handle( tdb->pkt );
+ session->retransmit_handle(tsd->get_pkt() );
- if( overlap < right->payload_size )
+ if ( overlap < right->payload_size )
{
- if( right->is_retransmit( rdata, rsize, rseq ) )
+ if ( right->is_retransmit(rdata, rsize, rseq) )
{
// All data was retransmitted
- session->retransmit_process( tdb->pkt );
+ session->retransmit_process(tsd->get_pkt() );
keep_segment = false;
}
else
// Don't want to count retransmits as overlaps or do anything
// else with them. Account for retransmits of multiple PDUs
// in one segment.
- if( is_segment_retransmit() )
+ if ( is_segment_retransmit() )
continue;
tcpStats.overlaps++;
overlap_count++;
int rc = insert_full_overlap();
- if( rc != STREAM_INSERT_OK )
+ if ( rc != STREAM_INSERT_OK )
return rc;
}
}
return STREAM_INSERT_OK;
}
-void SegmentOverlapEditor::drop_old_segment( void )
+void SegmentOverlapEditor::drop_old_segment(void)
{
- DebugFormat(DEBUG_STREAM_STATE, "full right overlap, dropping old segment at seq %d, size %d\n",
- right->seq, right->payload_size);
+ DebugFormat(DEBUG_STREAM_STATE,
+ "full right overlap, dropping old segment at seq %d, size %d\n",
+ right->seq, right->payload_size);
- TcpSegment* drop_seg = right;
+ TcpSegmentNode* drop_seg = right;
right = right->next;
- delete_reassembly_segment( drop_seg );
+ delete_reassembly_segment(drop_seg);
}
-int SegmentOverlapEditor::generate_bad_segment_event( void )
+int SegmentOverlapEditor::generate_bad_segment_event(void)
{
DebugFormat(DEBUG_STREAM_STATE, "bad segment: overlap with invalid sequence number"
- "(seq: %X seq_end: %X overlap: %lu\n", seq, seq_end, overlap);
- EventBadSegment();
+ "(seq: %X seq_end: %X overlap: %lu\n", seq, seq_end, overlap);
+ session->tel->EventBadSegment();
inc_tcp_discards();
return STREAM_INSERT_ANOMALY;
}
-int SegmentOverlapEditor::left_overlap_keep_first( void )
+int SegmentOverlapEditor::left_overlap_keep_first(void)
{
int rc = STREAM_INSERT_OK;
DebugFormat(DEBUG_STREAM_STATE, "left overlap %d\n", overlap);
- len = tdb->pkt->dsize;
+ len = tsd->get_pkt()->dsize;
overlap = left->seq + left->payload_size - seq;
- if( overlap > 0 )
+ if ( overlap > 0 )
{
// NOTE that overlap will always be less than left->size since
// seq is always greater than left->seq
overlap_count++;
DebugMessage(DEBUG_STREAM_STATE, "left overlap, honoring old data\n");
- if( SEQ_LT( left->seq, tdb->seq ) && SEQ_GT( left->seq + left->payload_size, tdb->seq + tdb->pkt->dsize ) )
+ if ( SEQ_LT(left->seq, tsd->get_seq() ) && SEQ_GT(left->seq + left->payload_size,
+ tsd->get_seq() + tsd->get_pkt()->dsize) )
{
if (tcp_ips_data == NORM_MODE_ON)
{
- unsigned offset = tdb->seq - left->seq;
- memcpy( ( uint8_t* ) tdb->pkt->data, left->payload + offset, tdb->pkt->dsize );
- tdb->pkt->packet_flags |= PKT_MODIFIED;
+ unsigned offset = tsd->get_seq() - left->seq;
+ memcpy( ( uint8_t* )tsd->get_pkt()->data, left->payload + offset,
+ tsd->get_pkt()->dsize);
+ tsd->get_pkt()->packet_flags |= PKT_MODIFIED;
}
normStats[PC_TCP_IPS_DATA][tcp_ips_data]++;
sfBase.iPegs[PERF_COUNT_TCP_IPS_DATA][tcp_ips_data]++;
}
- else if( SEQ_LT( left->seq, tdb->seq ) )
+ else if ( SEQ_LT(left->seq, tsd->get_seq() ) )
{
- if( tcp_ips_data == NORM_MODE_ON )
+ if ( tcp_ips_data == NORM_MODE_ON )
{
- unsigned offset = tdb->seq - left->seq;
- unsigned length = left->seq + left->payload_size - tdb->seq;
- memcpy( ( uint8_t* ) tdb->pkt->data, left->payload + offset, length );
- tdb->pkt->packet_flags |= PKT_MODIFIED;
+ unsigned offset = tsd->get_seq() - left->seq;
+ unsigned length = left->seq + left->payload_size - tsd->get_seq();
+ memcpy( ( uint8_t* )tsd->get_pkt()->data, left->payload + offset, length);
+ tsd->get_pkt()->packet_flags |= PKT_MODIFIED;
}
normStats[PC_TCP_IPS_DATA][tcp_ips_data]++;
}
seq += overlap;
- if( SEQ_LEQ( seq_end, seq ) )
+ if ( SEQ_LEQ(seq_end, seq) )
return generate_bad_segment_event();
}
DebugFormat(DEBUG_STREAM_STATE, "left overlap %d\n", overlap);
- len = tdb->pkt->dsize;
+ len = tsd->get_pkt()->dsize;
overlap = left->seq + left->payload_size - seq;
- if( overlap > 0 )
+ if ( overlap > 0 )
{
tcpStats.overlaps++;
overlap_count++;
- if( SEQ_LT( left->seq, seq ) && SEQ_GEQ( left->seq + left->payload_size, seq + len ) )
+ if ( SEQ_LT(left->seq, seq) && SEQ_GEQ(left->seq + left->payload_size, seq + len) )
{
// existing packet overlaps new on both sides. Drop the new data.
DebugMessage(DEBUG_STREAM_STATE, "left overlap, honoring old data\n");
seq += overlap;
- if( SEQ_LEQ( seq_end, seq ) )
+ if ( SEQ_LEQ(seq_end, seq) )
return generate_bad_segment_event();
}
/* Otherwise, trim the old data accordingly */
- left->payload_size -= ( int16_t ) overlap;
+ left->payload_size -= ( int16_t )overlap;
seg_bytes_logical -= overlap;
DebugMessage(DEBUG_STREAM_STATE, "left overlap, honoring new data\n");
}
return rc;
}
-int SegmentOverlapEditor::left_overlap_keep_last( void )
+int SegmentOverlapEditor::left_overlap_keep_last(void)
{
int rc = STREAM_INSERT_OK;
DebugFormat(DEBUG_STREAM_STATE, "left overlap %d\n", overlap);
- len = tdb->pkt->dsize;
+ len = tsd->get_pkt()->dsize;
overlap = left->seq + left->payload_size - seq;
- if( overlap > 0 )
+ if ( overlap > 0 )
{
tcpStats.overlaps++;
overlap_count++;
/* True "Last" policy" */
- if( SEQ_LT( left->seq, seq ) && SEQ_GT( left->seq + left->payload_size, seq + len ) )
+ if ( SEQ_LT(left->seq, seq) && SEQ_GT(left->seq + left->payload_size, seq + len) )
{
/* New data is overlapped on both sides by existing data. Existing data needs to be
* split and the new data inserted in the middle.
* Need to duplicate left. Adjust that seq by + (seq + len) and
* size by - (seq + len - left->seq).
*/
- int rc = dup_reassembly_segment( tdb->pkt, left, &right );
- if( rc != STREAM_INSERT_OK )
+ int rc = dup_reassembly_segment(tsd->get_pkt(), left, &right);
+ if ( rc != STREAM_INSERT_OK )
return rc;
- left->payload_size -= ( int16_t ) overlap;
+ left->payload_size -= ( int16_t )overlap;
seg_bytes_logical -= overlap;
right->seq = seq + len;
- uint16_t delta = ( int16_t ) ( right->seq - left->seq );
+ uint16_t delta = ( int16_t )( right->seq - left->seq );
right->payload_size -= delta;
right->payload += delta;
seg_bytes_logical -= delta;
}
else
{
- left->payload_size -= (int16_t) overlap;
+ left->payload_size -= (int16_t)overlap;
seg_bytes_logical -= overlap;
}
-
}
return rc;
}
-void SegmentOverlapEditor::right_overlap_truncate_existing( void )
+void SegmentOverlapEditor::right_overlap_truncate_existing(void)
{
DebugMessage(DEBUG_STREAM_STATE, "Got partial right overlap\n");
- if ( SEQ_EQ( right->seq, seq ) && ( reassembly_policy != ReassemblyPolicy::OS_LAST ) )
+ if ( SEQ_EQ(right->seq, seq) && ( reassembly_policy != ReassemblyPolicy::OS_LAST ) )
{
slide = ( right->seq + right->payload_size - seq );
seq += slide;
/* partial overlap */
right->seq += overlap;
right->payload += overlap;
- right->payload_size -= (int16_t) overlap;
+ right->payload_size -= (int16_t)overlap;
seg_bytes_logical -= overlap;
total_bytes_queued -= overlap;
}
}
-void SegmentOverlapEditor::right_overlap_truncate_new( void )
+void SegmentOverlapEditor::right_overlap_truncate_new(void)
{
if (tcp_ips_data == NORM_MODE_ON)
{
- unsigned offset = right->seq - tdb->seq;
- unsigned length = tdb->seq + tdb->pkt->dsize - right->seq;
- memcpy( ( uint8_t* ) tdb->pkt->data + offset, right->payload, length );
- tdb->pkt->packet_flags |= PKT_MODIFIED;
+ unsigned offset = right->seq - tsd->get_seq();
+ unsigned length = tsd->get_seq() + tsd->get_pkt()->dsize - right->seq;
+ memcpy( ( uint8_t* )tsd->get_pkt()->data + offset, right->payload, length);
+ tsd->get_pkt()->packet_flags |= PKT_MODIFIED;
}
normStats[PC_TCP_IPS_DATA][tcp_ips_data]++;
// REASSEMBLY_POLICY_FIRST:
// REASSEMBLY_POLICY_VISTA:
-int SegmentOverlapEditor::full_right_overlap_truncate_new( void )
+int SegmentOverlapEditor::full_right_overlap_truncate_new(void)
{
DebugMessage(DEBUG_STREAM_STATE, "Got full right overlap, truncating new\n");
- if( tcp_ips_data == NORM_MODE_ON )
+ if ( tcp_ips_data == NORM_MODE_ON )
{
- unsigned offset = right->seq - tdb->seq;
- memcpy( ( uint8_t* ) tdb->pkt->data + offset, right->payload, right->payload_size );
- tdb->pkt->packet_flags |= PKT_MODIFIED;
+ unsigned offset = right->seq - tsd->get_seq();
+ memcpy( ( uint8_t* )tsd->get_pkt()->data + offset, right->payload, right->payload_size);
+ tsd->get_pkt()->packet_flags |= PKT_MODIFIED;
}
normStats[PC_TCP_IPS_DATA][tcp_ips_data]++;
sfBase.iPegs[PERF_COUNT_TCP_IPS_DATA][tcp_ips_data]++;
- if( SEQ_EQ( right->seq, seq ) )
+ if ( SEQ_EQ(right->seq, seq) )
{
/* Overlap is greater than or equal to right->size
* slide gets set before insertion */
right = right->next;
/* Adjusted seq is fully overlapped */
- if( SEQ_EQ( seq, seq_end ) )
+ if ( SEQ_EQ(seq, seq_end) )
return generate_bad_segment_event();
}
else
/* insert this one, and see if we need to chunk it up
Adjust slide so that is correct relative to orig seq */
- slide = seq - tdb->seq;
- int rc = add_reassembly_segment( tdb, len, slide, trunc_len, seq, left );
- if( rc != STREAM_INSERT_OK )
+ slide = seq - tsd->get_seq();
+ int rc = add_reassembly_segment(*tsd, len, slide, trunc_len, seq, 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
// REASSEMBLY_POLICY_WINDOWS2K3:
// REASSEMBLY_POLICY_BSD:
// REASSEMBLY_POLICY_MACOS:
-int SegmentOverlapEditor::full_right_overlap_os1( void )
+int SegmentOverlapEditor::full_right_overlap_os1(void)
{
- if( SEQ_GEQ( seq_end, right->seq + right->payload_size ) && SEQ_LT( seq, right->seq ) )
+ if ( SEQ_GEQ(seq_end, right->seq + right->payload_size) && SEQ_LT(seq, right->seq) )
{
drop_old_segment();
}
else
{
int rc = full_right_overlap_truncate_new();
- if( rc != STREAM_INSERT_OK )
+ if ( rc != STREAM_INSERT_OK )
return rc;
}
// REASSEMBLY_POLICY_LINUX:
// REASSEMBLY_POLICY_HPUX10:
// REASSEMBLY_POLICY_IRIX:
-int SegmentOverlapEditor::full_right_overlap_os2( void )
+int SegmentOverlapEditor::full_right_overlap_os2(void)
{
- if( SEQ_GEQ( seq_end, right->seq + right->payload_size ) && SEQ_LT( seq, right->seq ) )
+ if ( SEQ_GEQ(seq_end, right->seq + right->payload_size) && SEQ_LT(seq, right->seq) )
{
drop_old_segment();
}
- else if( SEQ_GT( seq_end, right->seq + right->payload_size ) && SEQ_EQ( seq, right->seq ) )
+ else if ( SEQ_GT(seq_end, right->seq + right->payload_size) && SEQ_EQ(seq, right->seq) )
{
drop_old_segment();
}
else
{
int rc = full_right_overlap_truncate_new();
- if( rc != STREAM_INSERT_OK )
+ if ( rc != STREAM_INSERT_OK )
return rc;
}
// REASSEMBLY_POLICY_HPUX11:
// REASSEMBLY_POLICY_SOLARIS:
-int SegmentOverlapEditor::full_right_overlap_os3( void )
+int SegmentOverlapEditor::full_right_overlap_os3(void)
{
// If this packet is wholly overlapping and the same size as a previous one and we have not
// received the one immediately preceeding, we take the FIRST.
- if( SEQ_EQ( right->seq, seq ) && ( right->payload_size == len )
- && ( left && !SEQ_EQ( left->seq + left->payload_size, seq ) ) )
+ if ( SEQ_EQ(right->seq, seq) && ( right->payload_size == len )
+ && ( left && !SEQ_EQ(left->seq + left->payload_size, seq) ) )
{
trunc_len += overlap;
- if( SEQ_LEQ( ( int )( seq_end - trunc_len ), seq ) )
+ if ( SEQ_LEQ( ( int )( seq_end - trunc_len ), seq) )
return generate_bad_segment_event();
}
else
// REASSEMBLY_POLICY_OLD_LINUX:
// REASSEMBLY_POLICY_LAST:
-int SegmentOverlapEditor::full_right_overlap_os4( void )
+int SegmentOverlapEditor::full_right_overlap_os4(void)
{
drop_old_segment();
return STREAM_INSERT_OK;
}
-int SegmentOverlapEditor::full_right_overlap_os5( void )
+int SegmentOverlapEditor::full_right_overlap_os5(void)
{
return full_right_overlap_truncate_new();
}
+
+void SegmentOverlapEditor::print(void)
+{
+ LogMessage(" seglist_base_seq: %X\n", seglist_base_seq);
+ LogMessage(" seglist head: %p\n", (void*)seglist.head);
+ LogMessage(" seglist tail: %p\n", (void*)seglist.tail);
+ LogMessage(" seglist next: %p\n", (void*)seglist.next);
+ LogMessage(" seg_count: %d\n", seg_count);
+ LogMessage(" seg_bytes_total: %d\n", seg_bytes_total);
+ LogMessage(" seg_bytes_logical: %d\n", seg_bytes_logical);
+}
+
#define SEGMENT_OVERLAP_EDITOR_H
#include "tcp_defs.h"
-#include "tcp_segment.h"
+#include "tcp_segment_node.h"
#include "tcp_session.h"
#define STREAM_INSERT_OK 0
{
protected:
- SegmentOverlapEditor( void )
- : session( nullptr ), reassembly_policy(ReassemblyPolicy::OS_DEFAULT), seglist_base_seq(0),
- seg_count(0), seg_bytes_total(0), seg_bytes_logical(0), total_bytes_queued(0),
- total_segs_queued(0), overlap_count(0),
- tdb( nullptr), left( nullptr ), right( nullptr ), seq( 0 ), seq_end( 0 ),
- len( 0 ), overlap( 0 ), slide( 0 ), trunc_len( 0 ), rdata( nullptr ),
- rsize( 0 ), rseq( 0 ), keep_segment( true )
+ SegmentOverlapEditor(void)
+ : session(nullptr), reassembly_policy(ReassemblyPolicy::OS_DEFAULT), seglist_base_seq(0),
+ seg_count(0), seg_bytes_total(0), seg_bytes_logical(0), total_bytes_queued(0),
+ total_segs_queued(0), overlap_count(0),
+ tsd(nullptr), left(nullptr), right(nullptr), seq(0), seq_end(0),
+ len(0), overlap(0), slide(0), trunc_len(0), rdata(nullptr),
+ rsize(0), rseq(0), keep_segment(true)
{
tcp_ips_data = Normalize_GetMode(NORM_TCP_IPS);
}
- virtual ~SegmentOverlapEditor( void ) { }
+ virtual ~SegmentOverlapEditor(void) { }
- void init_soe( TcpDataBlock* tdb, TcpSegment* left, TcpSegment* right )
+ void init_soe(TcpSegmentDescriptor& tsd, TcpSegmentNode* left, TcpSegmentNode* right)
{
- this->tdb = tdb;
+ this->tsd = &tsd;
this->left = left;
this->right = right;
- seq = tdb->seq;
- seq_end = tdb->end_seq;
- len = tdb->pkt->dsize;
+ seq = tsd.get_seq();
+ seq_end = tsd.get_end_seq();
+ len = tsd.get_data_len();
overlap = 0;
slide = 0;
trunc_len = 0;
- rdata = tdb->pkt->data;
- rsize = tdb->pkt->dsize;
- rseq = tdb->seq;
+ rdata = tsd.get_pkt()->data;
+ rsize = tsd.get_data_len();
+ rseq = tsd.get_seq();
keep_segment = true;
}
- int eval_left( void );
- int eval_right( void );
-
- virtual bool is_segment_retransmit( void );
- virtual void drop_old_segment( void );
- virtual int generate_bad_segment_event( void );
-
- virtual int left_overlap_keep_first( void );
- virtual int left_overlap_trim_first( void );
- virtual int left_overlap_keep_last( void );
- virtual void right_overlap_truncate_existing( void );
- virtual void right_overlap_truncate_new( void );
- virtual int full_right_overlap_truncate_new( void );
- virtual int full_right_overlap_os1( void );
- virtual int full_right_overlap_os2( void );
- virtual int full_right_overlap_os3( void );
- virtual int full_right_overlap_os4( void );
- virtual int full_right_overlap_os5( void );
-
- virtual int insert_left_overlap( void ) = 0;
- virtual void insert_right_overlap( void ) = 0;
- virtual int insert_full_overlap( void ) = 0;
- virtual int add_reassembly_segment( TcpDataBlock*, int16_t len, uint32_t slide, uint32_t trunc,
- uint32_t seq, TcpSegment * ) = 0;
- virtual int dup_reassembly_segment(Packet *p, TcpSegment *left, TcpSegment **retSeg) = 0;
- virtual int delete_reassembly_segment( TcpSegment* seg ) = 0;
+ int eval_left(void);
+ int eval_right(void);
+
+ virtual bool is_segment_retransmit(void);
+ virtual void drop_old_segment(void);
+ virtual int generate_bad_segment_event(void);
+
+ virtual int left_overlap_keep_first(void);
+ virtual int left_overlap_trim_first(void);
+ virtual int left_overlap_keep_last(void);
+ virtual void right_overlap_truncate_existing(void);
+ virtual void right_overlap_truncate_new(void);
+ virtual int full_right_overlap_truncate_new(void);
+ virtual int full_right_overlap_os1(void);
+ virtual int full_right_overlap_os2(void);
+ virtual int full_right_overlap_os3(void);
+ virtual int full_right_overlap_os4(void);
+ virtual int full_right_overlap_os5(void);
+
+ virtual int insert_left_overlap(void) = 0;
+ virtual void insert_right_overlap(void) = 0;
+ virtual int insert_full_overlap(void) = 0;
+ virtual int add_reassembly_segment(TcpSegmentDescriptor&, int16_t len, uint32_t slide, uint32_t
+ trunc,
+ uint32_t seq, TcpSegmentNode*) = 0;
+ virtual int dup_reassembly_segment(Packet* p, TcpSegmentNode* left, TcpSegmentNode** retSeg) =
+ 0;
+ virtual int delete_reassembly_segment(TcpSegmentNode* seg) = 0;
+
+ virtual void print(void);
TcpSession* session;
ReassemblyPolicy reassembly_policy;
uint32_t total_segs_queued; /* number of segments queued (life) */
uint32_t overlap_count; /* overlaps encountered */
- TcpDataBlock* tdb;
- TcpSegment* left;
- TcpSegment* right;
+ TcpSegmentDescriptor* tsd;
+ TcpSegmentNode* left;
+ TcpSegmentNode* right;
uint32_t seq;
uint32_t seq_end;
uint16_t len;
};
#endif
+
class StreamTcp : public Inspector
{
public:
- StreamTcp(StreamTcpConfig*);
+ StreamTcp(TcpStreamConfig*);
~StreamTcp();
void show(SnortConfig*) override;
void eval(Packet*) override;
public:
- StreamTcpConfig* config;
+ TcpStreamConfig* config;
};
-StreamTcp::StreamTcp (StreamTcpConfig* c)
+StreamTcp::StreamTcp (TcpStreamConfig* c)
{
config = c;
}
void StreamTcp::show(SnortConfig*)
{
- TcpSession::show(config);
+ TcpStreamConfig::show_config(config);
}
bool StreamTcp::configure(SnortConfig*)
assert(false);
}
-StreamTcpConfig* get_tcp_cfg(Inspector* ins)
+TcpStreamConfig* get_tcp_cfg(Inspector* ins)
{
assert(ins);
return ((StreamTcp*)ins)->config;
#include "protocols/packet.h"
#include "tcp_defs.h"
-
-struct StreamTcpConfig
-{
- StreamPolicy policy;
- ReassemblyPolicy reassembly_policy;
-
- uint16_t flags;
- uint16_t flush_factor;
-
- uint32_t session_timeout;
- uint32_t max_window;
- uint32_t overlap_limit;
-
- uint32_t max_queued_bytes;
- uint32_t max_queued_segs;
-
- uint32_t max_consec_small_segs;
- uint32_t max_consec_small_seg_size;
-
- int hs_timeout;
- int footprint;
- unsigned paf_max;
-
- StreamTcpConfig();
-
- bool require_3whs();
- bool midstream_allowed(Packet*);
-};
+#include "tcp_stream_config.h"
// misc stuff
Session* get_tcp_session(Flow*);
-StreamTcpConfig* get_tcp_cfg(Inspector*);
+TcpStreamConfig* get_tcp_cfg(Inspector*);
void tcp_sinit();
void tcp_sterm();
void tcp_sum();
void tcp_stats();
void tcp_reset_stats();
-void tcp_show(StreamTcpConfig*);
+void tcp_show(TcpStreamConfig*);
#endif
+++ /dev/null
-//--------------------------------------------------------------------------
-// Copyright (C) 2015-2015 Cisco and/or its affiliates. All rights reserved.
-//
-// This program is free software; you can redistribute it and/or modify it
-// under the terms of the GNU General Public License Version 2 as published
-// by the Free Software Foundation. You may not use, modify or distribute
-// this program under any other version of the GNU General Public License.
-//
-// This program is distributed in the hope that it will be useful, but
-// WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-// General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License along
-// with this program; if not, write to the Free Software Foundation, Inc.,
-// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
-//--------------------------------------------------------------------------
-
-// tcp_closed_state.cc author davis mcpherson <davmcphe@@cisco.com>
-// Created on: Jul 30, 2015
-
-#include "tcp_closed_state.h"
-
-#include "stream/stream.h"
-
-#ifdef UNIT_TEST
-#include "catch/catch.hpp"
-#include "stream/libtcp/stream_tcp_unit_test.h"
-#endif
-
-TcpClosedState::TcpClosedState()
-{
- // TODO Auto-generated constructor stub
-
-}
-
-TcpClosedState::~TcpClosedState()
-{
- // TODO Auto-generated destructor stub
-}
-
-void TcpClosedState::syn_sent( TcpSegmentDescriptor &tcp_seg, TcpStreamTracker &tracker )
-{
- tracker.set_iss( tcp_seg.get_seq() );
- tracker.set_snd_una( tcp_seg.get_seq() + 1 );
- tracker.set_snd_nxt( tcp_seg.get_end_seq() );
- tracker.set_snd_wnd( tcp_seg.get_win() );
- tracker.set_ts_last_packet( tcp_seg.get_pkt()->pkth->ts.tv_sec );
-
- tracker.set_tcp_state( TcpStreamTracker::TCP_SYN_SENT );
-}
-
-void TcpClosedState::syn_recv(TcpSegmentDescriptor &tcp_seg, TcpStreamTracker &tracker)
-{
- default_state_action( &tcp_seg, &tracker, __func__ );
-}
-
-void TcpClosedState::syn_ack_sent(TcpSegmentDescriptor &tcp_seg, TcpStreamTracker &tracker)
-{
- default_state_action( &tcp_seg, &tracker, __func__ );
-}
-
-void TcpClosedState::syn_ack_recv(TcpSegmentDescriptor &tcp_seg, TcpStreamTracker &tracker)
-{
- default_state_action( &tcp_seg, &tracker, __func__ );
-}
-
-void TcpClosedState::ack_sent(TcpSegmentDescriptor &tcp_seg, TcpStreamTracker &tracker)
-{
- default_state_action( &tcp_seg, &tracker, __func__ );
-}
-
-void TcpClosedState::ack_recv(TcpSegmentDescriptor &tcp_seg, TcpStreamTracker &tracker)
-{
- default_state_action( &tcp_seg, &tracker, __func__ );
-}
-
-void TcpClosedState::data_seg_sent(TcpSegmentDescriptor &tcp_seg, TcpStreamTracker &tracker)
-{
- default_state_action( &tcp_seg, &tracker, __func__ );
-}
-
-void TcpClosedState::data_seg_recv(TcpSegmentDescriptor &tcp_seg, TcpStreamTracker &tracker)
-{
- default_state_action( &tcp_seg, &tracker, __func__ );
-}
-
-void TcpClosedState::fin_sent(TcpSegmentDescriptor &tcp_seg, TcpStreamTracker &tracker)
-{
- default_state_action( &tcp_seg, &tracker, __func__ );
-}
-
-void TcpClosedState::fin_recv(TcpSegmentDescriptor &tcp_seg, TcpStreamTracker &tracker)
-{
- default_state_action( &tcp_seg, &tracker, __func__ );
-}
-
-void TcpClosedState::rst_sent(TcpSegmentDescriptor &tcp_seg, TcpStreamTracker &tracker)
-{
- default_state_action( &tcp_seg, &tracker, __func__ );
-}
-
-void TcpClosedState::rst_recv(TcpSegmentDescriptor &tcp_seg, TcpStreamTracker &tracker)
-{
- default_state_action( &tcp_seg, &tracker, __func__ );
-}
-
-#ifdef UNIT_TEST
-
-TEST_CASE("TCP State Closed", "[tcp_closed_state][stream_tcp]")
-{
- // initialization code here
- Flow* flow = new Flow;
- TcpStateHandler* tsh = new TcpClosedState;
- TcpStreamTracker* client_tracker = new TcpStreamTracker( true );
-
- SECTION("syn_packet")
- {
- Packet* pkt = get_syn_packet( flow );
- REQUIRE( ( pkt != nullptr ) );
-
- SECTION("syn_sent")
- {
- flow->ssn_state.direction = FROM_CLIENT;
- TcpSegmentDescriptor tcp_seg( flow, pkt );
- client_tracker->set_tcp_event( tcp_seg, client_tracker->is_client_tracker( ) );
- tsh->eval( tcp_seg, *client_tracker );
- CHECK( TcpStreamTracker::TCP_SYN_SENT_EVENT == client_tracker->get_tcp_event() );
- CHECK( ( client_tracker->get_iss() == 9050 ) );
- CHECK( ( client_tracker->get_snd_una() == 9051 ) );
- CHECK( ( client_tracker->get_snd_nxt() == 9050 ) );
- CHECK( ( client_tracker->get_snd_wnd() == 8192 ) );
- }
-
- SECTION("syn_recv")
- {
- flow->ssn_state.direction = FROM_SERVER;
- TcpSegmentDescriptor tcp_seg( flow, pkt );
- client_tracker->set_tcp_event( tcp_seg, client_tracker->is_client_tracker( ) );
- tsh->eval( tcp_seg, *client_tracker );
- CHECK( ( tsh->get_tcp_event() == client_tracker->get_tcp_event() ) );
- }
-
- delete pkt;
- }
-
- SECTION("syn_ack_packet")
- {
- Packet* pkt = get_syn_ack_packet( flow );
- REQUIRE( ( pkt != nullptr ) );
-
- SECTION("syn_ack_sent")
- {
- flow->ssn_state.direction = FROM_CLIENT;
- TcpSegmentDescriptor tcp_seg( flow, pkt );
- client_tracker->set_tcp_event( tcp_seg, client_tracker->is_client_tracker( ) );
- tsh->eval( tcp_seg, *client_tracker );
- CHECK( ( tsh->get_tcp_event() == client_tracker->get_tcp_event() ) );
- }
-
- SECTION("syn_ack_recv")
- {
- flow->ssn_state.direction = FROM_SERVER;
- TcpSegmentDescriptor tcp_seg( flow, pkt );
- client_tracker->set_tcp_event( tcp_seg, client_tracker->is_client_tracker( ) );
- tsh->eval( tcp_seg, *client_tracker );
- CHECK( ( tsh->get_tcp_event() == client_tracker->get_tcp_event() ) );
- }
-
- delete pkt;
- }
-
- SECTION("ack_packet")
- {
- Packet* pkt = get_ack_packet( flow );
- REQUIRE( ( pkt != nullptr ) );
-
- SECTION("ack_sent")
- {
- flow->ssn_state.direction = FROM_CLIENT;
- TcpSegmentDescriptor tcp_seg( flow, pkt );
- client_tracker->set_tcp_event( tcp_seg, client_tracker->is_client_tracker( ) );
- tsh->eval( tcp_seg, *client_tracker );
- CHECK( ( tsh->get_tcp_event() == client_tracker->get_tcp_event() ) );
- }
-
- SECTION("ack_recv")
- {
- flow->ssn_state.direction = FROM_SERVER;
- TcpSegmentDescriptor tcp_seg( flow, pkt );
- client_tracker->set_tcp_event( tcp_seg, client_tracker->is_client_tracker( ) );
- tsh->eval( tcp_seg, *client_tracker );
- CHECK( ( tsh->get_tcp_event() == client_tracker->get_tcp_event() ) );
- }
-
- delete pkt;
- }
-
- SECTION("data_seg_packet")
- {
- Packet* pkt = get_data_packet( flow );
- REQUIRE( ( pkt != nullptr ) );
-
- SECTION("data_seg_sent")
- {
- flow->ssn_state.direction = FROM_CLIENT;
- TcpSegmentDescriptor tcp_seg( flow, pkt );
- client_tracker->set_tcp_event( tcp_seg, client_tracker->is_client_tracker( ) );
- tsh->eval( tcp_seg, *client_tracker );
- CHECK( ( tsh->get_tcp_event() == client_tracker->get_tcp_event() ) );
- }
-
- SECTION("data_seg_recv")
- {
- flow->ssn_state.direction = FROM_SERVER;
- TcpSegmentDescriptor tcp_seg( flow, pkt );
- client_tracker->set_tcp_event( tcp_seg, client_tracker->is_client_tracker( ) );
- tsh->eval( tcp_seg, *client_tracker );
- CHECK( ( tsh->get_tcp_event() == client_tracker->get_tcp_event() ) );
- }
-
- delete pkt;
- }
-
- SECTION("fin_packet")
- {
- Packet* pkt = get_fin_packet( flow );
- REQUIRE( ( pkt != nullptr ) );
-
- SECTION("fin_sent")
- {
- flow->ssn_state.direction = FROM_CLIENT;
- TcpSegmentDescriptor tcp_seg( flow, pkt );
- client_tracker->set_tcp_event( tcp_seg, client_tracker->is_client_tracker( ) );
- tsh->eval( tcp_seg, *client_tracker );
- CHECK( ( tsh->get_tcp_event() == client_tracker->get_tcp_event() ) );
- }
-
- SECTION("fin_recv")
- {
- flow->ssn_state.direction = FROM_SERVER;
- TcpSegmentDescriptor tcp_seg( flow, pkt );
- client_tracker->set_tcp_event( tcp_seg, client_tracker->is_client_tracker( ) );
- tsh->eval( tcp_seg, *client_tracker );
- CHECK( ( tsh->get_tcp_event() == client_tracker->get_tcp_event() ) );
- }
-
- delete pkt;
- }
-
- SECTION("rst_packet")
- {
- Packet* pkt = get_rst_packet( flow );
- REQUIRE( ( pkt != nullptr ));
-
- SECTION("rst_sent")
- {
- flow->ssn_state.direction = FROM_CLIENT;
- TcpSegmentDescriptor tcp_seg( flow, pkt );
- client_tracker->set_tcp_event( tcp_seg, client_tracker->is_client_tracker( ) );
- tsh->eval( tcp_seg, *client_tracker );
- CHECK( ( tsh->get_tcp_event() == client_tracker->get_tcp_event() ));
- }
-
- SECTION("rst_recv")
- {
- flow->ssn_state.direction = FROM_SERVER;
- TcpSegmentDescriptor tcp_seg( flow, pkt );
- client_tracker->set_tcp_event( tcp_seg, client_tracker->is_client_tracker( ) );
- tsh->eval( tcp_seg, *client_tracker );
- CHECK( ( tsh->get_tcp_event() == client_tracker->get_tcp_event() ) );
- }
-
- delete pkt;
- }
-
- delete flow;
- delete tsh;
- delete client_tracker;
-}
-
-#endif
+++ /dev/null
-//--------------------------------------------------------------------------
-// Copyright (C) 2015-2015 Cisco and/or its affiliates. All rights reserved.
-//
-// This program is free software; you can redistribute it and/or modify it
-// under the terms of the GNU General Public License Version 2 as published
-// by the Free Software Foundation. You may not use, modify or distribute
-// this program under any other version of the GNU General Public License.
-//
-// This program is distributed in the hope that it will be useful, but
-// WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-// General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License along
-// with this program; if not, write to the Free Software Foundation, Inc.,
-// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
-//--------------------------------------------------------------------------
-
-// tcp_closed_state.h author davis mcpherson <davmcphe@cisco.com>
-// Created on: Jul 30, 2015
-
-#ifndef TCP_CLOSED_STATE_H
-#define TCP_CLOSED_STATE_H
-
-#include "stream/libtcp/tcp_state_handler.h"
-
-class TcpClosedState: public TcpStateHandler
-{
-public:
- TcpClosedState();
- virtual ~TcpClosedState();
-
- void syn_sent(TcpSegmentDescriptor&, TcpStreamTracker&);
- void syn_recv(TcpSegmentDescriptor&, TcpStreamTracker&);
- void syn_ack_sent(TcpSegmentDescriptor&, TcpStreamTracker&);
- void syn_ack_recv(TcpSegmentDescriptor&, TcpStreamTracker&);
- void ack_sent(TcpSegmentDescriptor&, TcpStreamTracker&);
- void ack_recv(TcpSegmentDescriptor&, TcpStreamTracker&);
- void data_seg_sent(TcpSegmentDescriptor&, TcpStreamTracker&);
- void data_seg_recv(TcpSegmentDescriptor&, TcpStreamTracker&);
- void fin_sent(TcpSegmentDescriptor&, TcpStreamTracker&);
- void fin_recv(TcpSegmentDescriptor&, TcpStreamTracker&);
- void rst_sent(TcpSegmentDescriptor&, TcpStreamTracker&);
- void rst_recv(TcpSegmentDescriptor&, TcpStreamTracker&);
-};
-
-#endif
#include "tcp_reassembler.h"
#ifndef REG_TEST
-#define S5TraceTCP(pkt, flow, tdb, evt)
+#define S5TraceTCP(pkt, flow, tsd, evt)
#else
-#define LCL(p, x) (p->x - p->isn)
-#define RMT(p, x, q) (p->x - (q ? q->isn : 0))
+#define LCL(p, x) (p->x() - p->get_iss())
+#define RMT(p, x, q) (p->x - (q ? q->get_iss() : 0))
static const char* const statext[] =
{
- "NON", "LST", "SYR", "SYS", "EST", "CLW",
- "LAK", "FW1", "CLG", "FW2", "TWT", "CLD"
+ "LST", "SYS", "SYR", "EST", "FW1", "FW2", "CLW",
+ "CLG", "LAK", "TWT", "CLD", "NON"
};
static const char* const flushxt[] = { "IGN", "FPR", "PRE", "PRO", "PAF" };
// FIXIT-L this should not be thread specific
static THREAD_LOCAL int s5_trace_enabled = -1;
-static inline void TraceEvent(const Packet* p, TcpDataBlock*, uint32_t txd, uint32_t rxd)
+static inline void TraceEvent(const Packet* p, TcpSegmentDescriptor*, uint32_t txd, uint32_t rxd)
{
int i;
char flags[7] = "UAPRSF";
order = " (oos)";
fprintf(stdout, "\n" FMTu64("-3") " %s=0x%02x Seq=%-4u Ack=%-4u Win=%-4u Len=%-4u%s\n",
- //"\n" FMTu64("-3") " %s=0x%02x Seq=%-4u Ack=%-4u Win=%-4u Len=%-4u End=%-4u%s\n",
- pc.total_from_daq, flags, h->th_flags, ntohl(h->th_seq) - txd, ntohl(h->th_ack) - rxd, ntohs(h->th_win),
- p->dsize, order);
+ //"\n" FMTu64("-3") " %s=0x%02x Seq=%-4u Ack=%-4u Win=%-4u Len=%-4u End=%-4u%s\n",
+ pc.total_from_daq, flags, h->th_flags, ntohl(h->th_seq) - txd, ntohl(h->th_ack) - rxd,
+ ntohs(h->th_win), p->dsize, order);
}
static inline void TraceSession(const Flow* lws)
{
- fprintf( stdout, " LWS: ST=0x%x SF=0x%x CP=%u SP=%u\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=%u SP=%u\n", (unsigned)lws->session_state,
+ lws->ssn_state.session_flags, lws->client_port, lws->server_port);
}
static inline void TraceState(const TcpTracker* a, const TcpTracker* b, const char* s)
{
- uint32_t why = a->l_nxt_seq ? LCL(a, l_nxt_seq) : 0;
+ uint32_t why = a->get_snd_nxt() ? LCL(a, get_snd_nxt) : 0;
- fprintf(stdout, " %s ST=%s:%02x UA=%-4u NS=%-4u LW=%-5u RN=%-4u RW=%-4u ", s, statext[a->s_mgr.state],
- a->s_mgr.sub_state, LCL(a, l_unackd), why, a->l_window, RMT(a, r_nxt_ack, b), RMT(a, r_win_base, b));
+ fprintf(stdout, " %s ST=%s:%02x UA=%-4u NS=%-4u LW=%-5u RN=%-4u RW=%-4u ", s,
+ statext[a->get_tcp_state()], a->s_mgr.sub_state, LCL(a, get_snd_una), why,
+ a->get_snd_wnd( ), RMT(a, r_nxt_ack, b), RMT(a, r_win_base, b));
- if (a->s_mgr.state_queue)
- fprintf(stdout, "QS=%s QC=0x%02x QA=%-4u", statext[a->s_mgr.state_queue], a->s_mgr.expected_flags,
- RMT(a, s_mgr.transition_seq, b));
+ if ( a->s_mgr.state_queue != TcpStreamTracker::TCP_STATE_NONE )
+ fprintf(stdout, "QS=%s QC=0x%02x QA=%-4u", statext[a->s_mgr.state_queue],
+ a->s_mgr.expected_flags, RMT(a, s_mgr.transition_seq, b));
fprintf(stdout, "\n");
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->isn);
+ 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();
fprintf(stdout, "\n");
}
-static inline void TraceTCP(const Packet* p, const Flow* lws, TcpDataBlock* tdb, int event)
+static inline void TraceTCP(const Packet* p, const Flow* lws, TcpSegmentDescriptor* tsd, int event)
{
- const TcpSession* ssn = (TcpSession*) lws->session;
- const TcpTracker* srv = ssn ? &ssn->server : NULL;
- const TcpTracker* cli = ssn ? &ssn->client : NULL;
+ const TcpSession* ssn = (TcpSession*)lws->session;
+ const TcpTracker* srv = ssn ? ssn->server : NULL;
+ const TcpTracker* cli = ssn ? ssn->client : NULL;
- const char* cdir = "?", *sdir = "?";
+ const char* cdir = "?", * sdir = "?";
uint32_t txd = 0, rxd = 0;
if (p->packet_flags & PKT_FROM_SERVER)
if (ssn->tcp_init)
{
- txd = srv->isn;
- rxd = cli->isn;
+ txd = srv->get_iss();
+ rxd = cli->get_iss();
}
- } else if (p->packet_flags & PKT_FROM_CLIENT)
+ }
+ else if (p->packet_flags & PKT_FROM_CLIENT)
{
sdir = "SRV<";
cdir = "CLI>";
if (ssn->tcp_init)
{
- txd = cli->isn;
- rxd = srv->isn;
+ txd = cli->get_iss();
+ rxd = srv->get_iss();
}
}
- TraceEvent(p, tdb, txd, rxd);
+ TraceEvent(p, tsd, txd, rxd);
if (!ssn->tcp_init)
return;
}
}
-static inline void S5TraceTCP(const Packet* p, const Flow* lws, TcpDataBlock* tdb, int event)
+static inline void S5TraceTCP(const Packet* p, const Flow* lws, TcpSegmentDescriptor* tsd, int
+ event)
{
if (!s5_trace_enabled)
return;
s5_trace_enabled = atoi(s5t);
}
- TraceTCP(p, lws, tdb, event);
+ TraceTCP(p, lws, tsd, event);
}
+
#endif // REG_TEST
#endif
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
//--------------------------------------------------------------------------
-// tcp_defs.h author davis mcpherson <davmcphe@@cisco.com>
+// tcp_defs.h author davis mcpherson <davmcphe@cisco.com>
// Created on: Jul 31, 2015
#ifndef TCP_DEFS_H
#include "main/snort_debug.h"
#include "protocols/packet.h"
+#if 0
/* TCP states */
#define TCP_STATE_NONE 0
#define TCP_STATE_LISTEN 1
#define TCP_STATE_FIN_WAIT_2 9
#define TCP_STATE_TIME_WAIT 10
#define TCP_STATE_CLOSED 11
+#endif
/* actions */
#define ACTION_NOTHING 0x00000000
#define ACTION_LWSSN_CLOSED 0x00000800
#define ACTION_DISABLE_INSPECTION 0x00001000
-
#define TF_NONE 0x0000
#define TF_WSCALE 0x0001
#define TF_TSTAMP 0x0002
#define SUB_RST_SENT 0x04
#define SUB_FIN_SENT 0x08
+#define STREAM_UNALIGNED 0
+#define STREAM_ALIGNED 1
+
+#define STREAM_DEFAULT_MAX_QUEUED_BYTES 1048576 /* 1 MB */
+#define AVG_PKT_SIZE 400
+#define STREAM_DEFAULT_MAX_QUEUED_SEGS ( STREAM_DEFAULT_MAX_QUEUED_BYTES / AVG_PKT_SIZE )
+
+#define STREAM_DEFAULT_MAX_SMALL_SEG_SIZE 0 /* disabled */
+#define STREAM_DEFAULT_CONSEC_SMALL_SEGS 0 /* disabled */
+
+#define SLAM_MAX 4
+
// target-based policy types - changes to this enum require changes to stream_api.h::TCP_POLICIES
enum class StreamPolicy
{
};
// increment operator...
-inline StreamPolicy& operator++( StreamPolicy &c )
+inline StreamPolicy& operator++(StreamPolicy& c)
{
- if( c < StreamPolicy::OS_END_OF_LIST )
+ if ( c < StreamPolicy::OS_END_OF_LIST )
c = static_cast<StreamPolicy>( static_cast<int>(c) + 1 );
else
c = StreamPolicy::OS_END_OF_LIST;
};
// increment operator...
-inline ReassemblyPolicy& operator++( ReassemblyPolicy &c )
+inline ReassemblyPolicy& operator++(ReassemblyPolicy& c)
{
- if( c < ReassemblyPolicy::OS_END_OF_LIST )
+ if ( c < ReassemblyPolicy::OS_END_OF_LIST )
c = static_cast<ReassemblyPolicy>( static_cast<int>(c) + 1 );
else
c = ReassemblyPolicy::OS_END_OF_LIST;
STREAM_FLPOLICY_ON_DATA, /* protocol aware ips */
};
+#if 0
struct TcpDataBlock
{
Packet* pkt;
uint32_t end_seq;
uint32_t ts;
};
-
+#endif
//#define DEBUG_STREAM_EX
#ifdef DEBUG_STREAM_EX
#endif
#endif
+
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
//--------------------------------------------------------------------------
-// tcp_events.h author davis mcpherson <davmcphe@@cisco.com>
+// tcp_events.cc author davis mcpherson <davmcphe@@cisco.com>
// Created on: Jul 30, 2015
-#ifndef TCP_EVENTS_H
-#define TCP_EVENTS_H
-
#include "main/snort_config.h"
#include "events/event_queue.h"
#include "filters/sfrf.h"
#include "detection/rules.h"
+
#include "tcp_defs.h"
#include "tcp_module.h"
+#include "tcp_event_logger.h"
+
+void TcpEventLogger::set_tcp_internal_syn_event(void)
+{
+ tcp_events |= INTERNAL_EVENT_SYN_RECEIVED;
+}
-/* events */
-#define EVENT_SYN_ON_EST 0x00000001
-#define EVENT_DATA_ON_SYN 0x00000002
-#define EVENT_DATA_ON_CLOSED 0x00000004
-#define EVENT_BAD_TIMESTAMP 0x00000008
-#define EVENT_WINDOW_TOO_LARGE 0x00000010
-#define EVENT_DATA_AFTER_RESET 0x00000020
-#define EVENT_SESSION_HIJACK_CLIENT 0x00000040
-#define EVENT_SESSION_HIJACK_SERVER 0x00000080
-#define EVENT_DATA_WITHOUT_FLAGS 0x00000100
-#define EVENT_4WHS 0x00000200
-#define EVENT_NO_TIMESTAMP 0x00000400
-#define EVENT_BAD_RST 0x00000800
-#define EVENT_BAD_FIN 0x00001000
-#define EVENT_BAD_ACK 0x00002000
-#define EVENT_DATA_AFTER_RST_RCVD 0x00004000
-#define EVENT_WINDOW_SLAM 0x00008000
-#define EVENT_NO_3WHS 0x00010000
-
-static inline void EventSynOnEst()
+void TcpEventLogger::EventSynOnEst(void)
{
SnortEventqAdd(GID_STREAM_TCP, STREAM_TCP_SYN_ON_EST);
tcpStats.events++;
}
-static inline void EventExcessiveOverlap()
+void TcpEventLogger::EventExcessiveOverlap(void)
{
SnortEventqAdd(GID_STREAM_TCP, STREAM_TCP_EXCESSIVE_TCP_OVERLAPS);
tcpStats.events++;
}
-static inline void EventBadTimestamp()
+void TcpEventLogger::EventBadTimestamp(void)
{
SnortEventqAdd(GID_STREAM_TCP, STREAM_TCP_BAD_TIMESTAMP);
tcpStats.events++;
}
-static inline void EventWindowTooLarge()
+void TcpEventLogger::EventWindowTooLarge(void)
{
SnortEventqAdd(GID_STREAM_TCP, STREAM_TCP_WINDOW_TOO_LARGE);
tcpStats.events++;
}
-static inline void EventDataOnSyn()
+void TcpEventLogger::EventDataOnSyn(void)
{
SnortEventqAdd(GID_STREAM_TCP, STREAM_TCP_DATA_ON_SYN);
tcpStats.events++;
}
-static inline void EventDataOnClosed()
+void TcpEventLogger::EventDataOnClosed(void)
{
SnortEventqAdd(GID_STREAM_TCP, STREAM_TCP_DATA_ON_CLOSED);
tcpStats.events++;
}
-static inline void EventDataAfterReset()
+void TcpEventLogger::EventDataAfterReset(void)
{
SnortEventqAdd(GID_STREAM_TCP, STREAM_TCP_DATA_AFTER_RESET);
tcpStats.events++;
}
-static inline void EventBadSegment()
+void TcpEventLogger::EventBadSegment(void)
{
SnortEventqAdd(GID_STREAM_TCP, STREAM_TCP_BAD_SEGMENT);
tcpStats.events++;
}
-static inline void EventSessionHijackedClient()
+void TcpEventLogger::EventSessionHijackedClient(void)
{
SnortEventqAdd(GID_STREAM_TCP, STREAM_TCP_SESSION_HIJACKED_CLIENT);
tcpStats.events++;
}
-static inline void EventSessionHijackedServer()
+void TcpEventLogger::EventSessionHijackedServer(void)
{
SnortEventqAdd(GID_STREAM_TCP, STREAM_TCP_SESSION_HIJACKED_SERVER);
tcpStats.events++;
}
-static inline void EventDataWithoutFlags()
+void TcpEventLogger::EventDataWithoutFlags(void)
{
SnortEventqAdd(GID_STREAM_TCP, STREAM_TCP_DATA_WITHOUT_FLAGS);
tcpStats.events++;
}
-static inline void EventMaxSmallSegsExceeded()
+void TcpEventLogger::EventMaxSmallSegsExceeded(void)
{
SnortEventqAdd(GID_STREAM_TCP, STREAM_TCP_SMALL_SEGMENT);
tcpStats.events++;
}
-static inline void Event4whs()
+void TcpEventLogger::Event4whs(void)
{
SnortEventqAdd(GID_STREAM_TCP, STREAM_TCP_4WAY_HANDSHAKE);
tcpStats.events++;
}
-static inline void EventNoTimestamp()
+void TcpEventLogger::EventNoTimestamp(void)
{
SnortEventqAdd(GID_STREAM_TCP, STREAM_TCP_NO_TIMESTAMP);
tcpStats.events++;
}
-static inline void EventBadReset()
+void TcpEventLogger::EventBadReset(void)
{
SnortEventqAdd(GID_STREAM_TCP, STREAM_TCP_BAD_RST);
tcpStats.events++;
}
-static inline void EventBadFin()
+void TcpEventLogger::EventBadFin(void)
{
SnortEventqAdd(GID_STREAM_TCP, STREAM_TCP_BAD_FIN);
tcpStats.events++;
}
-static inline void EventBadAck()
+void TcpEventLogger::EventBadAck(void)
{
SnortEventqAdd(GID_STREAM_TCP, STREAM_TCP_BAD_ACK);
tcpStats.events++;
}
-static inline void EventDataAfterRstRcvd()
+void TcpEventLogger::EventDataAfterRstRcvd(void)
{
SnortEventqAdd(GID_STREAM_TCP, STREAM_TCP_DATA_AFTER_RST_RCVD);
tcpStats.events++;
}
-static inline void EventInternal(uint32_t eventSid)
+void TcpEventLogger::EventInternal(uint32_t eventSid)
{
if (!InternalEventIsEnabled(snort_conf->rate_filter_config, eventSid))
return;
tcpStats.internalEvents++;
- STREAM_DEBUG_WRAP( DebugMessage(DEBUG_STREAM_STATE, "Stream raised internal event %d\n", eventSid); );
+ STREAM_DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE, "Stream raised internal event %d\n",
+ eventSid); );
SnortEventqAdd(GENERATOR_INTERNAL, eventSid);
}
-static inline void EventWindowSlam()
+void TcpEventLogger::EventWindowSlam(void)
{
SnortEventqAdd(GID_STREAM_TCP, STREAM_TCP_WINDOW_SLAM);
tcpStats.events++;
}
-static inline void EventNo3whs()
+void TcpEventLogger::EventNo3whs(void)
{
SnortEventqAdd(GID_STREAM_TCP, STREAM_TCP_NO_3WHS);
tcpStats.events++;
}
-static inline void LogTcpEvents(int eventcode)
+void TcpEventLogger::log_tcp_events(void)
{
- if (!eventcode)
+ if ( !tcp_events )
return;
- if (eventcode & EVENT_SYN_ON_EST)
+ if (tcp_events & EVENT_SYN_ON_EST)
EventSynOnEst();
- if (eventcode & EVENT_DATA_ON_SYN)
+ if (tcp_events & EVENT_DATA_ON_SYN)
EventDataOnSyn();
- if (eventcode & EVENT_DATA_ON_CLOSED)
+ if (tcp_events & EVENT_DATA_ON_CLOSED)
EventDataOnClosed();
- if (eventcode & EVENT_BAD_TIMESTAMP)
+ if (tcp_events & EVENT_BAD_TIMESTAMP)
EventBadTimestamp();
- if (eventcode & EVENT_WINDOW_TOO_LARGE)
+ if (tcp_events & EVENT_WINDOW_TOO_LARGE)
EventWindowTooLarge();
- if (eventcode & EVENT_DATA_AFTER_RESET)
+ if (tcp_events & EVENT_DATA_AFTER_RESET)
EventDataAfterReset();
- if (eventcode & EVENT_SESSION_HIJACK_CLIENT)
+ if (tcp_events & EVENT_SESSION_HIJACK_CLIENT)
EventSessionHijackedClient();
- if (eventcode & EVENT_SESSION_HIJACK_SERVER)
+ if (tcp_events & EVENT_SESSION_HIJACK_SERVER)
EventSessionHijackedServer();
- if (eventcode & EVENT_DATA_WITHOUT_FLAGS)
+ if (tcp_events & EVENT_DATA_WITHOUT_FLAGS)
EventDataWithoutFlags();
- if (eventcode & EVENT_4WHS)
+ if (tcp_events & EVENT_4WHS)
Event4whs();
- if (eventcode & EVENT_NO_TIMESTAMP)
+ if (tcp_events & EVENT_NO_TIMESTAMP)
EventNoTimestamp();
- if (eventcode & EVENT_BAD_RST)
+ if (tcp_events & EVENT_BAD_RST)
EventBadReset();
- if (eventcode & EVENT_BAD_FIN)
+ if (tcp_events & EVENT_BAD_FIN)
EventBadFin();
- if (eventcode & EVENT_BAD_ACK)
+ if (tcp_events & EVENT_BAD_ACK)
EventBadAck();
- if (eventcode & EVENT_DATA_AFTER_RST_RCVD)
+ if (tcp_events & EVENT_DATA_AFTER_RST_RCVD)
EventDataAfterRstRcvd();
- if (eventcode & EVENT_WINDOW_SLAM)
+ if (tcp_events & EVENT_WINDOW_SLAM)
EventWindowSlam();
+
+ tcp_events = 0;
}
-#endif
--- /dev/null
+//--------------------------------------------------------------------------
+// Copyright (C) 2014-2015 Cisco and/or its affiliates. All rights reserved.
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License Version 2 as published
+// by the Free Software Foundation. You may not use, modify or distribute
+// this program under any other version of the GNU General Public License.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+//--------------------------------------------------------------------------
+
+// tcp_events.h author davis mcpherson <davmcphe@@cisco.com>
+// Created on: Jul 30, 2015
+
+#ifndef TCP_EVENT_LOGGER_H
+#define TCP_EVENT_LOGGER_H
+
+/* events */
+#define EVENT_SYN_ON_EST 0x00000001
+#define EVENT_DATA_ON_SYN 0x00000002
+#define EVENT_DATA_ON_CLOSED 0x00000004
+#define EVENT_BAD_TIMESTAMP 0x00000008
+#define EVENT_WINDOW_TOO_LARGE 0x00000010
+#define EVENT_DATA_AFTER_RESET 0x00000020
+#define EVENT_SESSION_HIJACK_CLIENT 0x00000040
+#define EVENT_SESSION_HIJACK_SERVER 0x00000080
+#define EVENT_DATA_WITHOUT_FLAGS 0x00000100
+#define EVENT_4WHS 0x00000200
+#define EVENT_NO_TIMESTAMP 0x00000400
+#define EVENT_BAD_RST 0x00000800
+#define EVENT_BAD_FIN 0x00001000
+#define EVENT_BAD_ACK 0x00002000
+#define EVENT_DATA_AFTER_RST_RCVD 0x00004000
+#define EVENT_WINDOW_SLAM 0x00008000
+#define EVENT_NO_3WHS 0x00010000
+
+class TcpEventLogger
+{
+public:
+ TcpEventLogger(void) :
+ tcp_events(0)
+ {
+ }
+
+ ~TcpEventLogger(void)
+ {
+ }
+
+ void clear_tcp_events(void)
+ {
+ tcp_events = 0;
+ }
+
+ void set_tcp_event(int eventcode)
+ {
+ tcp_events |= eventcode;
+ }
+
+ void set_tcp_internal_syn_event(void);
+
+ void EventSynOnEst(void);
+ void EventExcessiveOverlap(void);
+ void EventBadTimestamp(void);
+ void EventWindowTooLarge(void);
+ void EventDataOnSyn(void);
+ void EventDataOnClosed(void);
+ void EventDataAfterReset(void);
+ void EventBadSegment(void);
+ void EventSessionHijackedClient(void);
+ void EventSessionHijackedServer(void);
+ void EventDataWithoutFlags(void);
+ void EventMaxSmallSegsExceeded(void);
+ void Event4whs(void);
+ void EventNoTimestamp(void);
+ void EventBadReset(void);
+ void EventBadFin(void);
+ void EventBadAck(void);
+ void EventDataAfterRstRcvd(void);
+ void EventInternal(uint32_t eventSid);
+ void EventWindowSlam(void);
+ void EventNo3whs(void);
+ void log_tcp_events(void);
+
+private:
+ uint32_t tcp_events;
+};
+#endif
+
+++ /dev/null
-//--------------------------------------------------------------------------
-// Copyright (C) 2015-2015 Cisco and/or its affiliates. All rights reserved.
-//
-// This program is free software; you can redistribute it and/or modify it
-// under the terms of the GNU General Public License Version 2 as published
-// by the Free Software Foundation. You may not use, modify or distribute
-// this program under any other version of the GNU General Public License.
-//
-// This program is distributed in the hope that it will be useful, but
-// WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-// General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License along
-// with this program; if not, write to the Free Software Foundation, Inc.,
-// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
-//--------------------------------------------------------------------------
-
-// tcp_listen_state.cc author davis mcpherson <davmcphe@@cisco.com>
-// Created on: Jul 30, 2015
-
-#include "tcp_listen_state.h"
-
-TcpListenState::TcpListenState()
-{
- // TODO Auto-generated constructor stub
-
-}
-
-TcpListenState::~TcpListenState()
-{
- // TODO Auto-generated destructor stub
-}
-
THREAD_LOCAL ProfileStats s5TcpFlushPerfStats;
THREAD_LOCAL ProfileStats s5TcpBuildPacketPerfStats;
-const PegInfo tcp_pegs[] = {
+const PegInfo tcp_pegs[] =
+{
{ "sessions", "total sessions" },
{ "timeouts", "sessions timed out" },
{ "resyns", "SYN received on established session" },
return nullptr;
}
-StreamTcpConfig* StreamTcpModule::get_data()
+TcpStreamConfig* StreamTcpModule::get_data()
{
- StreamTcpConfig* temp = config;
+ TcpStreamConfig* temp = config;
config = nullptr;
return temp;
}
if ( config )
return false;
- config = new StreamTcpConfig;
+ config = new TcpStreamConfig;
return true;
}
#include "main/thread.h"
#include "framework/module.h"
#include "stream/stream.h"
+#include "tcp_stream_config.h"
#define GID_STREAM_TCP 129
{
tcpStats.discards++;
}
+
//-------------------------------------------------------------------------
// stream_tcp module
//-------------------------------------------------------------------------
#define MOD_HELP "stream inspector for TCP flow tracking and stream normalization and reassembly"
struct SnortConfig;
-struct StreamTcpConfig;
-class StreamTcpModule: public Module
+class StreamTcpModule : public Module
{
public:
StreamTcpModule();
return GID_STREAM_TCP;
}
- StreamTcpConfig* get_data();
+ TcpStreamConfig* get_data();
ProfileStats* get_profile(unsigned, const char*&, const char*&) const
- override;
+ override;
const PegInfo* get_pegs() const override;
PegCount* get_counts() const override;
private:
- StreamTcpConfig* config;
+ TcpStreamConfig* config;
};
#endif
#include "packet_io/active.h"
#include "tcp_normalizer.h"
-#include "tcp_events.h"
+#include "tcp_event_logger.h"
THREAD_LOCAL PegCount normStats[PC_MAX][NORM_MODE_MAX];
return ((st->s_mgr.sub_state & SUB_SETUP_OK) == SUB_SETUP_OK);
}
-TcpNormalizer::TcpNormalizer( StreamPolicy os_policy, TcpSession* session, TcpTracker* tracker ) :
- os_policy( os_policy ), session( session ), tracker( tracker ),
- peer_tracker( nullptr )
+TcpNormalizer::TcpNormalizer(StreamPolicy os_policy, TcpSession* session, TcpTracker* tracker) :
+ os_policy(os_policy), session(session), tracker(tracker),
+ peer_tracker(nullptr)
{
- tcp_ips_enabled = Normalize_IsEnabled( NORM_TCP_IPS );
- trim_syn = Normalize_GetMode( NORM_TCP_TRIM_SYN );
- trim_rst = Normalize_GetMode( NORM_TCP_TRIM_RST );
- trim_win = Normalize_GetMode( NORM_TCP_TRIM_WIN );
- trim_mss = Normalize_GetMode( NORM_TCP_TRIM_MSS );
- strip_ecn = Normalize_GetMode( NORM_TCP_ECN_STR );
- tcp_block = Normalize_GetMode( NORM_TCP_BLOCK );
- opt_block = Normalize_GetMode( NORM_TCP_OPT );
+ tcp_ips_enabled = Normalize_IsEnabled(NORM_TCP_IPS);
+ trim_syn = Normalize_GetMode(NORM_TCP_TRIM_SYN);
+ trim_rst = Normalize_GetMode(NORM_TCP_TRIM_RST);
+ trim_win = Normalize_GetMode(NORM_TCP_TRIM_WIN);
+ trim_mss = Normalize_GetMode(NORM_TCP_TRIM_MSS);
+ strip_ecn = Normalize_GetMode(NORM_TCP_ECN_STR);
+ tcp_block = Normalize_GetMode(NORM_TCP_BLOCK);
+ opt_block = Normalize_GetMode(NORM_TCP_OPT);
paws_ts_fudge = 0;
paws_drop_zero_ts = true;
}
void TcpNormalizer::trim_payload(
- TcpDataBlock* tdb, uint32_t max, NormMode mode, PegCounts peg, PerfCounts perfc)
+ TcpSegmentDescriptor& tsd, uint32_t max, NormMode mode, PegCounts peg, PerfCounts perfc)
{
if (mode == NORM_MODE_ON)
{
- uint16_t fat = tdb->pkt->dsize - max;
- tdb->pkt->dsize = max;
- tdb->pkt->packet_flags |= (PKT_MODIFIED | PKT_RESIZED);
- tdb->end_seq -= fat;
+ uint16_t fat = tsd.get_pkt()->dsize - max;
+ tsd.get_pkt()->dsize = max;
+ tsd.get_pkt()->packet_flags |= (PKT_MODIFIED | PKT_RESIZED);
+ tsd.set_end_seq(tsd.get_end_seq() - fat);
}
normStats[peg][mode]++;
}
bool TcpNormalizer::strip_tcp_timestamp(
- TcpDataBlock* tdb, const tcp::TcpOption* opt, NormMode mode)
+ TcpSegmentDescriptor& tsd, const tcp::TcpOption* opt, NormMode mode)
{
- normStats[PC_TCP_TS_NOP][mode]++;
- sfBase.iPegs[PERF_COUNT_TCP_TS_NOP][mode]++;
-
- if (mode == NORM_MODE_ON)
- {
- // set raw option bytes to nops
- memset((void *) opt, (uint32_t) tcp::TcpOptCode::NOP, tcp::TCPOLEN_TIMESTAMP);
- tdb->pkt->packet_flags |= PKT_MODIFIED;
- return true;
- }
-
- return false;
- }
-bool TcpNormalizer::packet_dropper(TcpDataBlock* tdb, NormFlags f)
+ normStats[PC_TCP_TS_NOP][mode]++;
+ sfBase.iPegs[PERF_COUNT_TCP_TS_NOP][mode]++;
+
+ if (mode == NORM_MODE_ON)
+ {
+ // set raw option bytes to nops
+ memset((void*)opt, (uint32_t)tcp::TcpOptCode::NOP, tcp::TCPOLEN_TIMESTAMP);
+ tsd.get_pkt()->packet_flags |= PKT_MODIFIED;
+ return true;
+ }
+
+ return false;
+}
+
+bool TcpNormalizer::packet_dropper(TcpSegmentDescriptor& tsd, NormFlags f)
{
const NormMode mode = (f == NORM_TCP_BLOCK) ? tcp_block : opt_block;
if (mode == NORM_MODE_ON)
{
- Active::drop_packet(tdb->pkt);
+ Active::drop_packet(tsd.get_pkt());
return true;
}
return false;
}
-void TcpNormalizer::trim_syn_payload(TcpDataBlock* tdb, uint32_t max)
+void TcpNormalizer::trim_syn_payload(TcpSegmentDescriptor& tsd, uint32_t max)
{
- if (tdb->pkt->dsize > max)
- trim_payload(tdb, max, trim_syn, PC_TCP_TRIM_SYN, PERF_COUNT_TCP_TRIM_SYN);
+ if (tsd.get_pkt()->dsize > max)
+ trim_payload(tsd, max, trim_syn, PC_TCP_TRIM_SYN, PERF_COUNT_TCP_TRIM_SYN);
}
-void TcpNormalizer::trim_rst_payload(TcpDataBlock* tdb, uint32_t max)
+void TcpNormalizer::trim_rst_payload(TcpSegmentDescriptor& tsd, uint32_t max)
{
- if (tdb->pkt->dsize > max)
- trim_payload(tdb, max, trim_rst, PC_TCP_TRIM_RST, PERF_COUNT_TCP_TRIM_RST);
+ if (tsd.get_pkt()->dsize > max)
+ trim_payload(tsd, max, trim_rst, PC_TCP_TRIM_RST, PERF_COUNT_TCP_TRIM_RST);
}
-void TcpNormalizer::trim_win_payload(TcpDataBlock* tdb, uint32_t max)
+void TcpNormalizer::trim_win_payload(TcpSegmentDescriptor& tsd, uint32_t max)
{
- if (tdb->pkt->dsize > max)
- trim_payload(tdb, max, trim_win, PC_TCP_TRIM_WIN, PERF_COUNT_TCP_TRIM_WIN);
+ if (tsd.get_pkt()->dsize > max)
+ trim_payload(tsd, max, trim_win, PC_TCP_TRIM_WIN, PERF_COUNT_TCP_TRIM_WIN);
}
-void TcpNormalizer::trim_mss_payload(TcpDataBlock* tdb, uint32_t max)
+void TcpNormalizer::trim_mss_payload(TcpSegmentDescriptor& tsd, uint32_t max)
{
- if (tdb->pkt->dsize > max)
- trim_payload(tdb, max, trim_mss, PC_TCP_TRIM_MSS, PERF_COUNT_TCP_TRIM_MSS);
+ if (tsd.get_pkt()->dsize > max)
+ trim_payload(tsd, max, trim_mss, PC_TCP_TRIM_MSS, PERF_COUNT_TCP_TRIM_MSS);
}
-void TcpNormalizer::ecn_tracker( tcp::TCPHdr* tcph, bool req3way )
+void TcpNormalizer::ecn_tracker(const tcp::TCPHdr* tcph, bool req3way)
{
- if( tcph->is_syn_ack() )
+ if ( tcph->is_syn_ack() )
{
- if( !req3way || session->ecn )
+ if ( !req3way || session->ecn )
session->ecn = ((tcph->th_flags & (TH_ECE | TH_CWR)) == TH_ECE);
}
- else if( tcph->is_syn() )
+ else if ( tcph->is_syn() )
session->ecn = tcph->are_flags_set(TH_ECE | TH_CWR);
}
-void TcpNormalizer::ecn_stripper( Packet* p )
+void TcpNormalizer::ecn_stripper(Packet* p)
{
if (!session->ecn && (p->ptrs.tcph->th_flags & (TH_ECE | TH_CWR)))
{
if (strip_ecn == NORM_MODE_ON)
{
- ((tcp::TCPHdr*) p->ptrs.tcph)->th_flags &= ~(TH_ECE | TH_CWR);
+ ((tcp::TCPHdr*)p->ptrs.tcph)->th_flags &= ~(TH_ECE | TH_CWR);
p->packet_flags |= PKT_MODIFIED;
}
}
// don't use the window if we may have missed scaling
-// one way zero window is unitialized
+// one way zero window is uninitialized
// two way zero window is actually closed (regardless of scaling)
-uint32_t TcpNormalizer::get_stream_window( TcpDataBlock* tdb )
+uint32_t TcpNormalizer::get_stream_window(TcpSegmentDescriptor& tsd)
{
int32_t window;
- if( tracker->l_window )
+ if ( tracker->get_snd_wnd() )
{
- if( !(session->flow->session_state & STREAM_STATE_MIDSTREAM ) )
- return tracker->l_window;
+ if ( !(session->flow->session_state & STREAM_STATE_MIDSTREAM ) )
+ return tracker->get_snd_wnd();
}
- else if( session->flow->two_way_traffic() )
- return tracker->l_window;
+ else if ( session->flow->two_way_traffic() )
+ return tracker->get_snd_wnd();
// ensure the data is in the window
- window = tdb->end_seq - tracker->r_win_base;
- if (window < 0)
+ window = tsd.get_end_seq() - tracker->r_win_base;
+ if ( window < 0 )
window = 0;
- return (uint32_t) window;
+ return (uint32_t)window;
}
-uint32_t TcpNormalizer::get_tcp_timestamp(TcpDataBlock* tdb, bool strip)
+uint32_t TcpNormalizer::get_tcp_timestamp(TcpSegmentDescriptor& tsd, bool strip)
{
DebugMessage(DEBUG_STREAM_STATE, "Getting timestamp...\n");
- tcp::TcpOptIterator iter(tdb->pkt->ptrs.tcph, tdb->pkt);
+ tcp::TcpOptIterator iter(tsd.get_tcph(), tsd.get_pkt() );
// using const because non-const is not supported
for (const tcp::TcpOption& opt : iter)
bool stripped = false;
if (strip)
- stripped = strip_tcp_timestamp(tdb, &opt, opt_block);
+ stripped = strip_tcp_timestamp(tsd, &opt, opt_block);
- if(!stripped)
+ if (!stripped)
{
- tdb->ts = EXTRACT_32BITS(opt.data);
- DebugFormat(DEBUG_STREAM_STATE, "Found timestamp %lu\n", tdb->ts);
+ tsd.set_ts(EXTRACT_32BITS(opt.data) );
+ DebugFormat(DEBUG_STREAM_STATE, "Found timestamp %lu\n", tsd.get_ts());
return TF_TSTAMP;
}
}
}
- tdb->ts = 0;
+ tsd.set_ts(0);
DebugMessage(DEBUG_STREAM_STATE, "No timestamp...\n");
return TF_NONE;
}
-bool TcpNormalizer::validate_rst_seq_geq( TcpDataBlock* tdb )
+bool TcpNormalizer::validate_rst_seq_geq(TcpSegmentDescriptor& tsd)
{
- DebugFormat(DEBUG_STREAM_STATE, "Checking end_seq (%X) > r_win_base (%X) && seq (%X) < r_nxt_ack(%X)\n",
- tdb->end_seq, tracker->r_win_base, tdb->seq, tracker->r_nxt_ack + get_stream_window( tdb ));
+ DebugFormat(DEBUG_STREAM_STATE,
+ "Checking end_seq (%X) > r_win_base (%X) && seq (%X) < r_nxt_ack(%X)\n",
+ tsd.get_end_seq(), tracker->r_win_base, tsd.get_seq(), tracker->r_nxt_ack +
+ get_stream_window(tsd));
- if (SEQ_GEQ(tdb->seq, tracker->r_nxt_ack))
+ if (SEQ_GEQ(tsd.get_seq(), tracker->r_nxt_ack))
{
DebugMessage(DEBUG_STREAM_STATE, "rst is valid seq (>= next seq)!\n");
return true;
return false;
}
-bool TcpNormalizer::validate_rst_end_seq_geq( TcpDataBlock* tdb )
+bool TcpNormalizer::validate_rst_end_seq_geq(TcpSegmentDescriptor& tsd)
{
- DebugFormat(DEBUG_STREAM_STATE, "Checking end_seq (%X) > r_win_base (%X) && seq (%X) < r_nxt_ack(%X)\n",
- tdb->end_seq, tracker->r_win_base, tdb->seq, tracker->r_nxt_ack + get_stream_window( tdb ));
-
- if (SEQ_GEQ(tdb->end_seq, tracker->r_win_base))
- {
- // reset must be admitted when window closed
- if (SEQ_LEQ(tdb->seq, tracker->r_win_base + get_stream_window( tdb )))
- {
- DebugMessage(DEBUG_STREAM_STATE, "rst is valid seq (within window)!\n");
- return true;
- }
- }
-
- DebugMessage(DEBUG_STREAM_STATE, "rst is not valid seq (within window)!\n");
- return false;
+ DebugFormat(DEBUG_STREAM_STATE,
+ "Checking end_seq (%X) > r_win_base (%X) && seq (%X) < r_nxt_ack(%X)\n",
+ tsd.get_end_seq(), tracker->r_win_base, tsd.get_seq(), tracker->r_nxt_ack +
+ get_stream_window(tsd));
+
+ if (SEQ_GEQ(tsd.get_end_seq(), tracker->r_win_base))
+ {
+ // reset must be admitted when window closed
+ if (SEQ_LEQ(tsd.get_seq(), tracker->r_win_base + get_stream_window(tsd)))
+ {
+ DebugMessage(DEBUG_STREAM_STATE, "rst is valid seq (within window)!\n");
+ return true;
+ }
+ }
+
+ DebugMessage(DEBUG_STREAM_STATE, "rst is not valid seq (within window)!\n");
+ return false;
}
-bool TcpNormalizer::validate_rst_seq_eq( TcpDataBlock* tdb )
+bool TcpNormalizer::validate_rst_seq_eq(TcpSegmentDescriptor& tsd)
{
- DebugFormat(DEBUG_STREAM_STATE, "Checking end_seq (%X) > r_win_base (%X) && seq (%X) < r_nxt_ack(%X)\n",
- tdb->end_seq, tracker->r_win_base, tdb->seq, tracker->r_nxt_ack + get_stream_window( tdb ));
+ DebugFormat(DEBUG_STREAM_STATE,
+ "Checking end_seq (%X) > r_win_base (%X) && seq (%X) < r_nxt_ack(%X)\n",
+ tsd.get_end_seq(), tracker->r_win_base, tsd.get_seq(), tracker->r_nxt_ack +
+ get_stream_window(tsd));
- if (SEQ_EQ(tdb->seq, tracker->r_nxt_ack))
+ if (SEQ_EQ(tsd.get_seq(), tracker->r_nxt_ack))
{
DebugMessage(DEBUG_STREAM_STATE, "rst is valid seq (next seq)!\n");
return true;
// for all states but syn-sent (handled above). however, we
// validate here based on how various implementations actually
// handle a rst.
-bool TcpNormalizer::validate_rst( TcpDataBlock* tdb )
+bool TcpNormalizer::validate_rst(TcpSegmentDescriptor& tsd)
{
- return validate_rst_seq_eq( tdb );
+ return validate_rst_seq_eq(tsd);
}
-int TcpNormalizer::validate_paws_timestamp( TcpDataBlock* tdb, int* eventcode )
+int TcpNormalizer::validate_paws_timestamp(TcpSegmentDescriptor& tsd)
{
- if( ( (int) ( ( tdb->ts - peer_tracker->ts_last ) + paws_ts_fudge ) ) < 0 )
+ if ( ( (int)( ( tsd.get_ts() - peer_tracker->ts_last ) + paws_ts_fudge ) ) < 0 )
{
DebugMessage(DEBUG_STREAM_STATE, "Packet outside PAWS window, dropping\n");
/* bail, we've got a packet outside the PAWS window! */
//inc_tcp_discards();
- *eventcode |= EVENT_BAD_TIMESTAMP;
- packet_dropper(tdb, NORM_TCP_OPT);
+ ( ( TcpSession* )tsd.get_flow()->session )->tel->set_tcp_event(EVENT_BAD_TIMESTAMP);
+ packet_dropper(tsd, NORM_TCP_OPT);
return ACTION_BAD_PKT;
}
- else if( ( peer_tracker->ts_last != 0 )
- && ( ( uint32_t ) tdb->pkt->pkth->ts.tv_sec > peer_tracker->ts_last_pkt + PAWS_24DAYS ) )
+ else if ( ( peer_tracker->ts_last != 0 )
+ && ( ( uint32_t )tsd.get_pkt()->pkth->ts.tv_sec > peer_tracker->get_ts_last_packet() +
+ PAWS_24DAYS ) )
{
/* this packet is from way too far into the future */
- DebugFormat(DEBUG_STREAM_STATE, "packet PAWS timestamp way too far ahead of last packet %d %d...\n",
- tdb->pkt->pkth->ts.tv_sec, peer_tracker->ts_last_pkt);
+ DebugFormat(DEBUG_STREAM_STATE,
+ "packet PAWS timestamp way too far ahead of last packet %d %d...\n",
+ tsd.get_pkt()->pkth->ts.tv_sec, peer_tracker->get_ts_last_packet() );
//inc_tcp_discards();
- *eventcode |= EVENT_BAD_TIMESTAMP;
- packet_dropper(tdb, NORM_TCP_OPT);
+ ( ( TcpSession* )tsd.get_flow()->session )->tel->set_tcp_event(EVENT_BAD_TIMESTAMP);
+ packet_dropper(tsd, NORM_TCP_OPT);
return ACTION_BAD_PKT;
}
else
}
}
-bool TcpNormalizer::is_paws_ts_checked_required( TcpDataBlock* )
+bool TcpNormalizer::is_paws_ts_checked_required(TcpSegmentDescriptor&)
{
return true;
}
-int TcpNormalizer::validate_paws( TcpDataBlock* tdb, int* eventcode, int* got_ts )
+int TcpNormalizer::validate_paws(TcpSegmentDescriptor& tsd, int* got_ts)
{
- *got_ts = get_tcp_timestamp(tdb, false);
- if (*got_ts)
+ *got_ts = get_tcp_timestamp(tsd, false);
+ if ( *got_ts )
{
- bool check_ts = is_paws_ts_checked_required( tdb );
+ bool check_ts = is_paws_ts_checked_required(tsd);
- if (check_ts)
- return validate_paws_timestamp( tdb, eventcode );
+ if ( check_ts )
+ return validate_paws_timestamp(tsd);
else
return ACTION_NOTHING;
}
// we've got a packet with no timestamp, but 3whs indicated talker was doing
// timestamps. This breaks protocol, however, some servers still ack the packet
// with the missing timestamp. Log an alert, but continue to process the packet
- DebugMessage(DEBUG_STREAM_STATE, "packet no timestamp, had one earlier from this side...ok for now...\n");
- *eventcode |= EVENT_NO_TIMESTAMP;
+ DebugMessage(DEBUG_STREAM_STATE,
+ "packet no timestamp, had one earlier from this side...ok for now...\n");
+ ( ( TcpSession* )tsd.get_flow()->session )->tel->set_tcp_event(EVENT_NO_TIMESTAMP);
/* Ignore the timestamp for this first packet, next one will checked. */
- if (tracker->config->policy == StreamPolicy::OS_SOLARIS)
+ if ( session->config->policy == StreamPolicy::OS_SOLARIS )
tracker->flags &= ~TF_TSTAMP;
- packet_dropper(tdb, NORM_TCP_OPT);
+ packet_dropper(tsd, NORM_TCP_OPT);
return ACTION_NOTHING;
}
}
-int TcpNormalizer::handle_paws_no_timestamps(TcpDataBlock* tdb, int* eventcode, int* got_ts)
+int TcpNormalizer::handle_paws_no_timestamps(TcpSegmentDescriptor& tsd, int* got_ts)
{
// if we are not handling timestamps, and this isn't a syn (only), and we have seen a
// valid 3way setup, then we strip (nop) the timestamp option. this includes the cases
// where we disable timestamp handling.
- int strip = ( SetupOK( peer_tracker ) && SetupOK( tracker ) );
+ int strip = ( SetupOK(peer_tracker) && SetupOK(tracker) );
DebugMessage(DEBUG_STREAM_STATE, "listener not doing timestamps...\n");
- *got_ts = get_tcp_timestamp(tdb, strip);
+ *got_ts = get_tcp_timestamp(tsd, strip);
if (*got_ts)
{
if (!(peer_tracker->flags & TF_TSTAMP))
{
// SYN skipped, may have missed talker's timestamp , so set it now.
peer_tracker->flags |= TF_TSTAMP;
- if (tdb->ts == 0)
+ if (tsd.get_ts() == 0)
peer_tracker->flags |= TF_TSTAMP_ZERO;
}
// Only valid to test this if listener is using timestamps. Otherwise, timestamp
// in this packet is not used, regardless of its value.
- if ( ( paws_drop_zero_ts && ( tdb->ts == 0 ) ) && ( tracker->flags & TF_TSTAMP ) )
+ if ( ( paws_drop_zero_ts && ( tsd.get_ts() == 0 ) ) && ( tracker->flags & TF_TSTAMP ) )
{
DebugMessage(DEBUG_STREAM_STATE, "Packet with 0 timestamp, dropping\n");
- *eventcode |= EVENT_BAD_TIMESTAMP;
+ ( ( TcpSession* )tsd.get_flow()->session )->tel->set_tcp_event(EVENT_BAD_TIMESTAMP);
return ACTION_BAD_PKT;
}
}
return ACTION_NOTHING;
}
-int TcpNormalizer::handle_paws(TcpDataBlock* tdb, int* eventcode, int* got_ts)
+int TcpNormalizer::handle_paws(TcpSegmentDescriptor& tsd, int* got_ts)
{
- if ( tdb->pkt->ptrs.tcph->is_rst() )
+ if ( tsd.get_tcph()->is_rst() )
return ACTION_NOTHING;
#if 0
- if ( tdb->pkt->ptrs.tcph->is_ack() && Normalize_IsEnabled(NORM_TCP_OPT) )
+ if ( tsd.get_tcph()->is_ack() && Normalize_IsEnabled(NORM_TCP_OPT) )
{
// FIXIT-L validate tsecr here (check that it was previously sent)
// checking for the most recent ts is easy enough must check if
if ((peer_tracker->flags & TF_TSTAMP) && (tracker->flags & TF_TSTAMP))
{
DebugMessage(DEBUG_STREAM_STATE, "Checking timestamps for PAWS\n");
- return validate_paws( tdb, eventcode, got_ts );
+ return validate_paws(tsd, got_ts);
}
- else if (tdb->pkt->ptrs.tcph->is_syn_only())
+ else if (tsd.get_tcph()->is_syn_only())
{
- *got_ts = get_tcp_timestamp(tdb, 0);
+ *got_ts = get_tcp_timestamp(tsd, 0);
if (*got_ts)
peer_tracker->flags |= TF_TSTAMP;
}
else
{
- return handle_paws_no_timestamps( tdb, eventcode, got_ts );
+ return handle_paws_no_timestamps(tsd, got_ts);
}
}
-uint16_t TcpNormalizer::set_urg_offset( const tcp::TCPHdr* tcph, uint16_t dsize )
+uint16_t TcpNormalizer::set_urg_offset(const tcp::TCPHdr* tcph, uint16_t dsize)
{
uint16_t urg_offset = 0;
- if(tcph->are_flags_set( TH_URG) )
+ if (tcph->are_flags_set(TH_URG) )
{
urg_offset = tcph->urp();
return urg_offset;
}
+
virtual ~TcpNormalizer( ) { }
- virtual bool packet_dropper (TcpDataBlock*, NormFlags );
- virtual void trim_syn_payload( TcpDataBlock*, uint32_t max = 0 );
- virtual void trim_rst_payload( TcpDataBlock*, uint32_t max = 0 );
- virtual void trim_win_payload( TcpDataBlock*, uint32_t max = 0 );
- virtual void trim_mss_payload( TcpDataBlock*, uint32_t max = 0 );
- virtual void ecn_tracker( tcp::TCPHdr*, bool req3way );
- virtual void ecn_stripper( Packet* );
- virtual uint32_t get_stream_window( TcpDataBlock* );
- virtual uint32_t get_tcp_timestamp( TcpDataBlock *, bool strip );
- virtual int handle_paws( TcpDataBlock*, int*, int* );
- virtual bool validate_rst( TcpDataBlock* );
- virtual int handle_repeated_syn( TcpDataBlock* ) = 0;
- virtual uint16_t set_urg_offset( const tcp::TCPHdr* tcph, uint16_t dsize );
-
- static const PegInfo* get_normalization_pegs( void );
- static NormPegs get_normalization_counts( unsigned& );
-
- void set_peer_tracker( TcpTracker* peer_tracker )
+ virtual bool packet_dropper (TcpSegmentDescriptor&, NormFlags);
+ virtual void trim_syn_payload(TcpSegmentDescriptor&, uint32_t max = 0);
+ virtual void trim_rst_payload(TcpSegmentDescriptor&, uint32_t max = 0);
+ virtual void trim_win_payload(TcpSegmentDescriptor&, uint32_t max = 0);
+ virtual void trim_mss_payload(TcpSegmentDescriptor&, uint32_t max = 0);
+ virtual void ecn_tracker(const tcp::TCPHdr*, bool req3way);
+ virtual void ecn_stripper(Packet*);
+ virtual uint32_t get_stream_window(TcpSegmentDescriptor&);
+ virtual uint32_t get_tcp_timestamp(TcpSegmentDescriptor&, bool strip);
+ virtual int handle_paws(TcpSegmentDescriptor&, int*);
+ virtual bool validate_rst(TcpSegmentDescriptor&);
+ virtual int handle_repeated_syn(TcpSegmentDescriptor&) = 0;
+ virtual uint16_t set_urg_offset(const tcp::TCPHdr* tcph, uint16_t dsize);
+
+ static const PegInfo* get_normalization_pegs(void);
+ static NormPegs get_normalization_counts(unsigned&);
+
+ void set_peer_tracker(TcpTracker* peer_tracker)
{
this->peer_tracker = peer_tracker;
}
}
protected:
- TcpNormalizer( StreamPolicy, TcpSession*, TcpTracker* );
- virtual void trim_payload( TcpDataBlock*, uint32_t, NormMode, PegCounts, PerfCounts );
- virtual bool strip_tcp_timestamp( TcpDataBlock*, const tcp::TcpOption*, NormMode );
- virtual bool validate_rst_seq_geq( TcpDataBlock* );
- virtual bool validate_rst_end_seq_geq( TcpDataBlock* );
- virtual bool validate_rst_seq_eq( TcpDataBlock* );
-
- virtual int validate_paws_timestamp( TcpDataBlock*, int* );
- virtual bool is_paws_ts_checked_required( TcpDataBlock* );
- virtual int validate_paws( TcpDataBlock*, int*, int* );
- virtual int handle_paws_no_timestamps( TcpDataBlock*, int* , int* );
+ TcpNormalizer(StreamPolicy, TcpSession*, TcpTracker*);
+ virtual void trim_payload(TcpSegmentDescriptor&, uint32_t, NormMode, PegCounts, PerfCounts);
+ virtual bool strip_tcp_timestamp(TcpSegmentDescriptor&, const tcp::TcpOption*, NormMode);
+ virtual bool validate_rst_seq_geq(TcpSegmentDescriptor&);
+ virtual bool validate_rst_end_seq_geq(TcpSegmentDescriptor&);
+ virtual bool validate_rst_seq_eq(TcpSegmentDescriptor&);
+
+ virtual int validate_paws_timestamp(TcpSegmentDescriptor&);
+ virtual bool is_paws_ts_checked_required(TcpSegmentDescriptor&);
+ virtual int validate_paws(TcpSegmentDescriptor&, int*);
+ virtual int handle_paws_no_timestamps(TcpSegmentDescriptor&, int*);
StreamPolicy os_policy;
TcpSession* session;
};
#endif
+
class TcpNormalizerFirst : public TcpNormalizer
{
public:
- TcpNormalizerFirst( TcpSession* session, TcpTracker* tracker ) :
- TcpNormalizer( StreamPolicy::OS_FIRST, session, tracker )
+ TcpNormalizerFirst(TcpSession* session, TcpTracker* tracker) :
+ TcpNormalizer(StreamPolicy::OS_FIRST, session, tracker)
{ }
- int handle_repeated_syn( TcpDataBlock* ) override;
+ int handle_repeated_syn(TcpSegmentDescriptor&) override;
};
class TcpNormalizerLast : public TcpNormalizer
{
public:
- TcpNormalizerLast( TcpSession* session, TcpTracker* tracker ) :
- TcpNormalizer( StreamPolicy::OS_LAST, session, tracker )
+ TcpNormalizerLast(TcpSession* session, TcpTracker* tracker) :
+ TcpNormalizer(StreamPolicy::OS_LAST, session, tracker)
{ }
- int handle_repeated_syn( TcpDataBlock* ) override;
+ int handle_repeated_syn(TcpSegmentDescriptor&) override;
};
class TcpNormalizerLinux : public TcpNormalizer
{
public:
- TcpNormalizerLinux( TcpSession* session, TcpTracker* tracker ) :
- TcpNormalizer( StreamPolicy::OS_LINUX, session, tracker )
+ TcpNormalizerLinux(TcpSession* session, TcpTracker* tracker) :
+ TcpNormalizer(StreamPolicy::OS_LINUX, session, tracker)
{
// Linux 2.6 accepts timestamp values that are off by one. so set fudge factor */
paws_ts_fudge = 1;
}
- bool validate_rst( TcpDataBlock* ) override;
- bool is_paws_ts_checked_required( TcpDataBlock* ) override;
- int handle_repeated_syn( TcpDataBlock* ) override;
- uint16_t set_urg_offset( const tcp::TCPHdr* tcph, uint16_t dsize ) override;
-
+ bool validate_rst(TcpSegmentDescriptor&) override;
+ bool is_paws_ts_checked_required(TcpSegmentDescriptor&) override;
+ int handle_repeated_syn(TcpSegmentDescriptor&) override;
+ uint16_t set_urg_offset(const tcp::TCPHdr* tcph, uint16_t dsize) override;
};
class TcpNormalizerOldLinux : public TcpNormalizer
{
public:
- TcpNormalizerOldLinux( TcpSession* session, TcpTracker* tracker ) :
- TcpNormalizer( StreamPolicy::OS_OLD_LINUX, session, tracker )
+ TcpNormalizerOldLinux(TcpSession* session, TcpTracker* tracker) :
+ TcpNormalizer(StreamPolicy::OS_OLD_LINUX, session, tracker)
{
paws_drop_zero_ts = false;
}
- bool validate_rst( TcpDataBlock* ) override;
- bool is_paws_ts_checked_required( TcpDataBlock* ) override;
- int handle_repeated_syn( TcpDataBlock* ) override;
- uint16_t set_urg_offset( const tcp::TCPHdr* tcph, uint16_t dsize ) override;
-
+ bool validate_rst(TcpSegmentDescriptor&) override;
+ bool is_paws_ts_checked_required(TcpSegmentDescriptor&) override;
+ int handle_repeated_syn(TcpSegmentDescriptor&) override;
+ uint16_t set_urg_offset(const tcp::TCPHdr* tcph, uint16_t dsize) override;
};
class TcpNormalizerBSD : public TcpNormalizer
{
public:
- TcpNormalizerBSD( TcpSession* session, TcpTracker* tracker ) :
- TcpNormalizer( StreamPolicy::OS_BSD, session, tracker )
+ TcpNormalizerBSD(TcpSession* session, TcpTracker* tracker) :
+ TcpNormalizer(StreamPolicy::OS_BSD, session, tracker)
{ }
- bool validate_rst( TcpDataBlock* ) override;
- int handle_repeated_syn( TcpDataBlock* ) override;
+ bool validate_rst(TcpSegmentDescriptor&) override;
+ int handle_repeated_syn(TcpSegmentDescriptor&) override;
};
class TcpNormalizerMacOS : public TcpNormalizer
{
public:
- TcpNormalizerMacOS( TcpSession* session, TcpTracker* tracker ) :
- TcpNormalizer( StreamPolicy::OS_MACOS, session, tracker )
+ TcpNormalizerMacOS(TcpSession* session, TcpTracker* tracker) :
+ TcpNormalizer(StreamPolicy::OS_MACOS, session, tracker)
{ }
- int handle_repeated_syn( TcpDataBlock* ) override;
+ int handle_repeated_syn(TcpSegmentDescriptor&) override;
};
class TcpNormalizerSolaris : public TcpNormalizer
{
public:
- TcpNormalizerSolaris( TcpSession* session, TcpTracker* tracker ) :
- TcpNormalizer( StreamPolicy::OS_SOLARIS, session, tracker )
+ TcpNormalizerSolaris(TcpSession* session, TcpTracker* tracker) :
+ TcpNormalizer(StreamPolicy::OS_SOLARIS, session, tracker)
{
paws_drop_zero_ts = false;
}
- bool validate_rst( TcpDataBlock* ) override;
- int handle_repeated_syn( TcpDataBlock* ) override;
+ bool validate_rst(TcpSegmentDescriptor&) override;
+ int handle_repeated_syn(TcpSegmentDescriptor&) override;
};
class TcpNormalizerIrix : public TcpNormalizer
{
public:
- TcpNormalizerIrix( TcpSession* session, TcpTracker* tracker ) :
- TcpNormalizer( StreamPolicy::OS_IRIX, session, tracker )
+ TcpNormalizerIrix(TcpSession* session, TcpTracker* tracker) :
+ TcpNormalizer(StreamPolicy::OS_IRIX, session, tracker)
{ }
- int handle_repeated_syn( TcpDataBlock* ) override;
+ int handle_repeated_syn(TcpSegmentDescriptor&) override;
};
class TcpNormalizerHpux11 : public TcpNormalizer
{
public:
- TcpNormalizerHpux11( TcpSession* session, TcpTracker* tracker ) :
- TcpNormalizer( StreamPolicy::OS_HPUX11, session, tracker )
+ TcpNormalizerHpux11(TcpSession* session, TcpTracker* tracker) :
+ TcpNormalizer(StreamPolicy::OS_HPUX11, session, tracker)
{ }
- bool validate_rst( TcpDataBlock* ) override;
- bool is_paws_ts_checked_required( TcpDataBlock* ) override;
- int handle_repeated_syn( TcpDataBlock* ) override;
+ bool validate_rst(TcpSegmentDescriptor&) override;
+ bool is_paws_ts_checked_required(TcpSegmentDescriptor&) override;
+ int handle_repeated_syn(TcpSegmentDescriptor&) override;
};
class TcpNormalizerHpux10 : public TcpNormalizer
{
public:
- TcpNormalizerHpux10( TcpSession* session, TcpTracker* tracker ) :
- TcpNormalizer( StreamPolicy::OS_HPUX10, session, tracker )
+ TcpNormalizerHpux10(TcpSession* session, TcpTracker* tracker) :
+ TcpNormalizer(StreamPolicy::OS_HPUX10, session, tracker)
{ }
- int handle_repeated_syn( TcpDataBlock* ) override;
+ int handle_repeated_syn(TcpSegmentDescriptor&) override;
};
class TcpNormalizerWindows : public TcpNormalizer
{
public:
- TcpNormalizerWindows( TcpSession* session, TcpTracker* tracker ) :
- TcpNormalizer( StreamPolicy::OS_WINDOWS, session, tracker )
+ TcpNormalizerWindows(TcpSession* session, TcpTracker* tracker) :
+ TcpNormalizer(StreamPolicy::OS_WINDOWS, session, tracker)
{
paws_drop_zero_ts = false;
}
- bool is_paws_ts_checked_required( TcpDataBlock* ) override;
- int handle_repeated_syn( TcpDataBlock* ) override;
+ bool is_paws_ts_checked_required(TcpSegmentDescriptor&) override;
+ int handle_repeated_syn(TcpSegmentDescriptor&) override;
};
class TcpNormalizerWindows2K3 : public TcpNormalizer
{
public:
- TcpNormalizerWindows2K3( TcpSession* session, TcpTracker* tracker ) :
- TcpNormalizer( StreamPolicy::OS_WINDOWS2K3, session, tracker )
+ TcpNormalizerWindows2K3(TcpSession* session, TcpTracker* tracker) :
+ TcpNormalizer(StreamPolicy::OS_WINDOWS2K3, session, tracker)
{
paws_drop_zero_ts = false;
}
- bool is_paws_ts_checked_required( TcpDataBlock* ) override;
- int handle_repeated_syn( TcpDataBlock* ) override;
+ bool is_paws_ts_checked_required(TcpSegmentDescriptor&) override;
+ int handle_repeated_syn(TcpSegmentDescriptor&) override;
};
class TcpNormalizerVista : public TcpNormalizer
{
public:
- TcpNormalizerVista( TcpSession* session, TcpTracker* tracker ) :
- TcpNormalizer( StreamPolicy::OS_VISTA, session, tracker )
+ TcpNormalizerVista(TcpSession* session, TcpTracker* tracker) :
+ TcpNormalizer(StreamPolicy::OS_VISTA, session, tracker)
{
paws_drop_zero_ts = false;
}
- bool is_paws_ts_checked_required( TcpDataBlock*) override;
- int handle_repeated_syn( TcpDataBlock* ) override;
+ bool is_paws_ts_checked_required(TcpSegmentDescriptor&) override;
+ int handle_repeated_syn(TcpSegmentDescriptor&) override;
};
class TcpNormalizerProxy : public TcpNormalizer
{
public:
- TcpNormalizerProxy( TcpSession* session, TcpTracker* tracker ) :
- TcpNormalizer( StreamPolicy::OS_PROXY, session, tracker )
+ TcpNormalizerProxy(TcpSession* session, TcpTracker* tracker) :
+ TcpNormalizer(StreamPolicy::OS_PROXY, session, tracker)
{ }
- bool validate_rst(TcpDataBlock* ) override;
- int handle_paws( TcpDataBlock*,int*, int* ) override;
- int handle_repeated_syn( TcpDataBlock* ) override;
+ bool validate_rst(TcpSegmentDescriptor&) override;
+ int handle_paws(TcpSegmentDescriptor&, int*) override;
+ int handle_repeated_syn(TcpSegmentDescriptor&) override;
};
-TcpNormalizer* TcpNormalizerFactory::create( StreamPolicy os_policy, TcpSession* session,
- TcpTracker* tracker, TcpTracker* peer )
+TcpNormalizer* TcpNormalizerFactory::create(TcpSession* session, StreamPolicy os_policy,
+ TcpTracker* tracker, TcpTracker* peer)
{
TcpNormalizer* normalizer;
switch (os_policy)
{
case StreamPolicy::OS_FIRST:
- normalizer = new TcpNormalizerFirst( session, tracker );
+ normalizer = new TcpNormalizerFirst(session, tracker);
break;
case StreamPolicy::OS_LAST:
- normalizer = new TcpNormalizerLast( session, tracker );
+ normalizer = new TcpNormalizerLast(session, tracker);
break;
case StreamPolicy::OS_LINUX:
- normalizer = new TcpNormalizerLinux( session, tracker );
+ normalizer = new TcpNormalizerLinux(session, tracker);
break;
case StreamPolicy::OS_OLD_LINUX:
- normalizer = new TcpNormalizerOldLinux( session, tracker );
+ normalizer = new TcpNormalizerOldLinux(session, tracker);
break;
case StreamPolicy::OS_BSD:
- normalizer = new TcpNormalizerBSD( session, tracker );
+ normalizer = new TcpNormalizerBSD(session, tracker);
break;
case StreamPolicy::OS_MACOS:
- normalizer = new TcpNormalizerMacOS( session, tracker );
+ normalizer = new TcpNormalizerMacOS(session, tracker);
break;
case StreamPolicy::OS_SOLARIS:
- normalizer = new TcpNormalizerSolaris( session, tracker );
+ normalizer = new TcpNormalizerSolaris(session, tracker);
break;
case StreamPolicy::OS_IRIX:
- normalizer = new TcpNormalizerIrix( session, tracker );
+ normalizer = new TcpNormalizerIrix(session, tracker);
break;
case StreamPolicy::OS_HPUX11:
- normalizer = new TcpNormalizerHpux11( session, tracker );
+ normalizer = new TcpNormalizerHpux11(session, tracker);
break;
case StreamPolicy::OS_HPUX10:
- normalizer = new TcpNormalizerHpux10( session, tracker );
+ normalizer = new TcpNormalizerHpux10(session, tracker);
break;
case StreamPolicy::OS_WINDOWS:
- normalizer = new TcpNormalizerWindows( session, tracker );
+ normalizer = new TcpNormalizerWindows(session, tracker);
break;
case StreamPolicy::OS_WINDOWS2K3:
- normalizer = new TcpNormalizerWindows2K3( session, tracker );
+ normalizer = new TcpNormalizerWindows2K3(session, tracker);
break;
case StreamPolicy::OS_VISTA:
- normalizer = new TcpNormalizerVista( session, tracker );
+ normalizer = new TcpNormalizerVista(session, tracker);
break;
case StreamPolicy::OS_PROXY:
- normalizer = new TcpNormalizerProxy( session, tracker );
+ normalizer = new TcpNormalizerProxy(session, tracker);
break;
default:
- normalizer = new TcpNormalizerBSD( session, tracker );
+ normalizer = new TcpNormalizerBSD(session, tracker);
break;
}
- normalizer->set_peer_tracker( peer );
+ normalizer->set_peer_tracker(peer);
return normalizer;
}
-static inline int handle_repeated_syn_mswin( TcpTracker* talker, TcpTracker* listener,
- TcpDataBlock* tdb, TcpSession* session )
+static inline int handle_repeated_syn_mswin(TcpTracker* talker, TcpTracker* listener,
+ TcpSegmentDescriptor& tsd, TcpSession* session)
{
/* Windows has some strange behaviour here. If the sequence of the reset is the
* next expected sequence, it Resets. Otherwise it ignores the 2nd SYN.
*/
- if (SEQ_EQ(tdb->seq, listener->r_nxt_ack))
+ if (SEQ_EQ(tsd.get_seq(), listener->r_nxt_ack))
{
- DebugMessage(DEBUG_STREAM_STATE, "Got syn on established windows ssn, which causes Reset, bailing\n");
- session->flow->set_session_flags( SSNFLAG_RESET );
- talker->s_mgr.state = TCP_STATE_CLOSED;
+ DebugMessage(DEBUG_STREAM_STATE,
+ "Got syn on established windows ssn, which causes Reset, bailing\n");
+ session->flow->set_session_flags(SSNFLAG_RESET);
+ talker->set_tcp_state(TcpStreamTracker::TCP_CLOSED);
return ACTION_RST;
}
else
{
- DebugMessage(DEBUG_STREAM_STATE, "Got syn on established windows ssn, not causing Reset, bailing\n");
+ DebugMessage(DEBUG_STREAM_STATE,
+ "Got syn on established windows ssn, not causing Reset, bailing\n");
inc_tcp_discards();
return ACTION_NOTHING;
}
}
-static inline int handle_repeated_syn_bsd( TcpTracker* talker, TcpDataBlock* tdb, TcpSession* session )
+static inline int handle_repeated_syn_bsd(TcpTracker* talker, TcpSegmentDescriptor& tsd,
+ TcpSession* session)
{
/* If its not a retransmission of the actual SYN... RESET */
- if (!SEQ_EQ(tdb->seq, talker->isn))
- {
- DebugMessage(DEBUG_STREAM_STATE, "Got syn on established ssn, which causes Reset, bailing\n");
- session->flow->set_session_flags( SSNFLAG_RESET );
- talker->s_mgr.state = TCP_STATE_CLOSED;
- return ACTION_RST;
- }
- else
- {
- DebugMessage(DEBUG_STREAM_STATE, "Got syn on established ssn, not causing Reset, bailing\n");
- inc_tcp_discards();
- return ACTION_NOTHING;
- }
+ if (!SEQ_EQ(tsd.get_seq(), talker->get_iss()))
+ {
+ DebugMessage(DEBUG_STREAM_STATE,
+ "Got syn on established ssn, which causes Reset, bailing\n");
+ session->flow->set_session_flags(SSNFLAG_RESET);
+ talker->set_tcp_state(TcpStreamTracker::TCP_CLOSED);
+ return ACTION_RST;
+ }
+ else
+ {
+ DebugMessage(DEBUG_STREAM_STATE,
+ "Got syn on established ssn, not causing Reset, bailing\n");
+ inc_tcp_discards();
+ return ACTION_NOTHING;
+ }
}
// Linux, Win2k3 et al. do not support timestamps if the 3whs used a 0 timestamp.
-static inline bool paws_3whs_zero_ts_not_supported(TcpTracker* talker, TcpTracker* listener )
+static inline bool paws_3whs_zero_ts_not_supported(TcpTracker* talker, TcpTracker* listener)
{
bool check_ts = true;
}
// Older Linux ( <= 2.2 kernel ), Win32 (non 2K3) allow the 3whs to use a 0 timestamp.
-static inline bool paws_3whs_zero_ts_supported(TcpTracker* talker, TcpTracker* listener, TcpDataBlock* tdb)
+static inline bool paws_3whs_zero_ts_supported(TcpTracker* talker, TcpTracker* listener,
+ TcpSegmentDescriptor& tsd)
{
bool check_ts = true;
- if( talker->flags & TF_TSTAMP_ZERO )
+ if ( talker->flags & TF_TSTAMP_ZERO )
{
talker->flags &= ~TF_TSTAMP_ZERO;
- if( SEQ_EQ( listener->r_nxt_ack, tdb->seq ) )
+ if ( SEQ_EQ(listener->r_nxt_ack, tsd.get_seq() ) )
{
// Ignore timestamp for this first packet, save to check on next
- talker->ts_last = tdb->ts;
+ talker->ts_last = tsd.get_ts();
check_ts = false;
}
}
return check_ts;
}
-static inline uint16_t set_urg_offset_linux( const tcp::TCPHdr* tcph, uint16_t dsize )
+static inline uint16_t set_urg_offset_linux(const tcp::TCPHdr* tcph, uint16_t dsize)
{
uint16_t urg_offset = 0;
- if(tcph->are_flags_set( TH_URG) )
+ if (tcph->are_flags_set(TH_URG) )
{
urg_offset = tcph->urp();
- // Linux, Old linux discard data from urgent pointer If urg pointer is 0,
- // it's treated as a 1
- if (tcph->urp() < dsize)
- if (urg_offset == 0)
- urg_offset = 1;
+ // Linux, Old linux discard data from urgent pointer If urg pointer is 0,
+ // it's treated as a 1
+ if (tcph->urp() < dsize)
+ if (urg_offset == 0)
+ urg_offset = 1;
}
return urg_offset;
}
-int TcpNormalizerFirst::handle_repeated_syn( TcpDataBlock* tdb )
+int TcpNormalizerFirst::handle_repeated_syn(TcpSegmentDescriptor& tsd)
{
- return handle_repeated_syn_bsd( peer_tracker, tdb, session );
+ return handle_repeated_syn_bsd(peer_tracker, tsd, session);
}
-int TcpNormalizerLast::handle_repeated_syn( TcpDataBlock* tdb )
+int TcpNormalizerLast::handle_repeated_syn(TcpSegmentDescriptor& tsd)
{
- return handle_repeated_syn_bsd( peer_tracker, tdb, session );
+ return handle_repeated_syn_bsd(peer_tracker, tsd, session);
}
-bool TcpNormalizerLinux::validate_rst( TcpDataBlock *tdb )
+bool TcpNormalizerLinux::validate_rst(TcpSegmentDescriptor& tsd)
{
- return validate_rst_end_seq_geq( tdb );
+ return validate_rst_end_seq_geq(tsd);
}
-bool TcpNormalizerLinux::is_paws_ts_checked_required( TcpDataBlock* )
+bool TcpNormalizerLinux::is_paws_ts_checked_required(TcpSegmentDescriptor&)
{
- return paws_3whs_zero_ts_not_supported( peer_tracker, tracker );
+ return paws_3whs_zero_ts_not_supported(peer_tracker, tracker);
}
-int TcpNormalizerLinux::handle_repeated_syn( TcpDataBlock* tdb )
+int TcpNormalizerLinux::handle_repeated_syn(TcpSegmentDescriptor& tsd)
{
- return handle_repeated_syn_bsd( peer_tracker, tdb, session );
+ return handle_repeated_syn_bsd(peer_tracker, tsd, session);
}
-uint16_t TcpNormalizerLinux::set_urg_offset( const tcp::TCPHdr* tcph, uint16_t dsize )
+uint16_t TcpNormalizerLinux::set_urg_offset(const tcp::TCPHdr* tcph, uint16_t dsize)
{
- return set_urg_offset_linux( tcph, dsize );
+ return set_urg_offset_linux(tcph, dsize);
}
-bool TcpNormalizerOldLinux::validate_rst( TcpDataBlock *tdb )
+bool TcpNormalizerOldLinux::validate_rst(TcpSegmentDescriptor& tsd)
{
- return validate_rst_end_seq_geq( tdb );
+ return validate_rst_end_seq_geq(tsd);
}
-bool TcpNormalizerOldLinux::is_paws_ts_checked_required( TcpDataBlock* tdb)
+bool TcpNormalizerOldLinux::is_paws_ts_checked_required(TcpSegmentDescriptor& tsd)
{
- return paws_3whs_zero_ts_supported( peer_tracker, tracker, tdb );
+ return paws_3whs_zero_ts_supported(peer_tracker, tracker, tsd);
}
-int TcpNormalizerOldLinux::handle_repeated_syn( TcpDataBlock* tdb )
+int TcpNormalizerOldLinux::handle_repeated_syn(TcpSegmentDescriptor& tsd)
{
- return handle_repeated_syn_bsd( peer_tracker, tdb, session );
+ return handle_repeated_syn_bsd(peer_tracker, tsd, session);
}
-uint16_t TcpNormalizerOldLinux::set_urg_offset( const tcp::TCPHdr* tcph, uint16_t dsize )
+uint16_t TcpNormalizerOldLinux::set_urg_offset(const tcp::TCPHdr* tcph, uint16_t dsize)
{
- return set_urg_offset_linux( tcph, dsize );
+ return set_urg_offset_linux(tcph, dsize);
}
-bool TcpNormalizerBSD::validate_rst( TcpDataBlock *tdb )
+bool TcpNormalizerBSD::validate_rst(TcpSegmentDescriptor& tsd)
{
- return validate_rst_end_seq_geq( tdb );
+ return validate_rst_end_seq_geq(tsd);
}
-int TcpNormalizerBSD::handle_repeated_syn( TcpDataBlock* tdb )
+int TcpNormalizerBSD::handle_repeated_syn(TcpSegmentDescriptor& tsd)
{
- return handle_repeated_syn_bsd( peer_tracker, tdb, session );
+ return handle_repeated_syn_bsd(peer_tracker, tsd, session);
}
-int TcpNormalizerMacOS::handle_repeated_syn( TcpDataBlock* )
+int TcpNormalizerMacOS::handle_repeated_syn(TcpSegmentDescriptor&)
{
/* MACOS ignores a 2nd SYN, regardless of the sequence number. */
- DebugMessage(DEBUG_STREAM_STATE, "Got syn on established macos ssn, not causing Reset, bailing\n");
+ DebugMessage(DEBUG_STREAM_STATE,
+ "Got syn on established macos ssn, not causing Reset, bailing\n");
inc_tcp_discards();
return ACTION_NOTHING;
}
-bool TcpNormalizerSolaris::validate_rst( TcpDataBlock* tdb )
+bool TcpNormalizerSolaris::validate_rst(TcpSegmentDescriptor& tsd)
{
- return validate_rst_end_seq_geq( tdb );
+ return validate_rst_end_seq_geq(tsd);
}
-int TcpNormalizerSolaris::handle_repeated_syn( TcpDataBlock* tdb )
+int TcpNormalizerSolaris::handle_repeated_syn(TcpSegmentDescriptor& tsd)
{
- return handle_repeated_syn_bsd( peer_tracker, tdb, session );
+ return handle_repeated_syn_bsd(peer_tracker, tsd, session);
}
-int TcpNormalizerIrix::handle_repeated_syn( TcpDataBlock* tdb )
+int TcpNormalizerIrix::handle_repeated_syn(TcpSegmentDescriptor& tsd)
{
- return handle_repeated_syn_bsd( peer_tracker, tdb, session );
+ return handle_repeated_syn_bsd(peer_tracker, tsd, session);
}
-bool TcpNormalizerHpux11::validate_rst( TcpDataBlock *tdb )
+bool TcpNormalizerHpux11::validate_rst(TcpSegmentDescriptor& tsd)
{
- return validate_rst_seq_geq( tdb );
+ return validate_rst_seq_geq(tsd);
}
-bool TcpNormalizerHpux11::is_paws_ts_checked_required( TcpDataBlock* tdb )
+bool TcpNormalizerHpux11::is_paws_ts_checked_required(TcpSegmentDescriptor& tsd)
{
/* HPUX 11 ignores timestamps for out of order segments */
- if ((tracker->flags & TF_MISSING_PKT) || !SEQ_EQ(tracker->r_nxt_ack, tdb->seq))
+ if ((tracker->flags & TF_MISSING_PKT) || !SEQ_EQ(tracker->r_nxt_ack, tsd.get_seq()))
return false;
else
return true;
}
-int TcpNormalizerHpux11::handle_repeated_syn( TcpDataBlock* tdb )
+int TcpNormalizerHpux11::handle_repeated_syn(TcpSegmentDescriptor& tsd)
{
- return handle_repeated_syn_bsd( peer_tracker, tdb, session );
+ return handle_repeated_syn_bsd(peer_tracker, tsd, session);
}
-int TcpNormalizerHpux10::handle_repeated_syn( TcpDataBlock* tdb )
+int TcpNormalizerHpux10::handle_repeated_syn(TcpSegmentDescriptor& tsd)
{
- return handle_repeated_syn_bsd( peer_tracker, tdb, session );
+ return handle_repeated_syn_bsd(peer_tracker, tsd, session);
}
-bool TcpNormalizerWindows::is_paws_ts_checked_required( TcpDataBlock* tdb)
+bool TcpNormalizerWindows::is_paws_ts_checked_required(TcpSegmentDescriptor& tsd)
{
- return paws_3whs_zero_ts_supported( peer_tracker, tracker, tdb );
+ return paws_3whs_zero_ts_supported(peer_tracker, tracker, tsd);
}
-int TcpNormalizerWindows::handle_repeated_syn( TcpDataBlock *tdb )
+int TcpNormalizerWindows::handle_repeated_syn(TcpSegmentDescriptor& tsd)
{
- return handle_repeated_syn_mswin( peer_tracker, tracker, tdb, session );
+ return handle_repeated_syn_mswin(peer_tracker, tracker, tsd, session);
}
-
-int TcpNormalizerWindows2K3::handle_repeated_syn( TcpDataBlock *tdb )
+int TcpNormalizerWindows2K3::handle_repeated_syn(TcpSegmentDescriptor& tsd)
{
- return handle_repeated_syn_mswin( peer_tracker, tracker, tdb, session );
+ return handle_repeated_syn_mswin(peer_tracker, tracker, tsd, session);
}
-bool TcpNormalizerWindows2K3::is_paws_ts_checked_required( TcpDataBlock* )
+bool TcpNormalizerWindows2K3::is_paws_ts_checked_required(TcpSegmentDescriptor&)
{
- return paws_3whs_zero_ts_not_supported( peer_tracker, tracker );
+ return paws_3whs_zero_ts_not_supported(peer_tracker, tracker);
}
-bool TcpNormalizerVista::is_paws_ts_checked_required( TcpDataBlock* tdb)
+bool TcpNormalizerVista::is_paws_ts_checked_required(TcpSegmentDescriptor& tsd)
{
- return paws_3whs_zero_ts_supported( peer_tracker, tracker, tdb );
+ return paws_3whs_zero_ts_supported(peer_tracker, tracker, tsd);
}
-int TcpNormalizerVista::handle_repeated_syn( TcpDataBlock *tdb )
+int TcpNormalizerVista::handle_repeated_syn(TcpSegmentDescriptor& tsd)
{
- return handle_repeated_syn_mswin( peer_tracker, tracker, tdb, session );
+ return handle_repeated_syn_mswin(peer_tracker, tracker, tsd, session);
}
-bool TcpNormalizerProxy::validate_rst( TcpDataBlock *tdb )
+bool TcpNormalizerProxy::validate_rst(TcpSegmentDescriptor& tsd)
{
#ifndef DEBUG_MSGS
- UNUSED( tdb );
+ UNUSED(tsd);
#endif
// FIXIT - will session->flow ever be null? i would think not, remove this check if possible
- if( session->flow )
+ if ( session->flow )
{
- DebugFormat(DEBUG_STREAM_STATE, "Proxy Normalizer - Not Valid\n end_seq (%X) > r_win_base (%X) && seq (%X) < r_nxt_ack(%X)\n",
- tdb->end_seq, tracker->r_win_base, tdb->seq, tracker->r_nxt_ack + get_stream_window( tdb ));
+ DebugFormat(DEBUG_STREAM_STATE,
+ "Proxy Normalizer - Not Valid\n end_seq (%X) > r_win_base (%X) && seq (%X) < r_nxt_ack(%X)\n",
+ tsd.get_end_seq(), tracker->r_win_base, tsd.get_seq(), tracker->r_nxt_ack +
+ get_stream_window(tsd));
}
return false;
}
-int TcpNormalizerProxy::handle_paws(TcpDataBlock*, int*, int*)
+int TcpNormalizerProxy::handle_paws(TcpSegmentDescriptor&, int*)
{
return ACTION_NOTHING;
}
-int TcpNormalizerProxy::handle_repeated_syn( TcpDataBlock* )
+int TcpNormalizerProxy::handle_repeated_syn(TcpSegmentDescriptor&)
{
return ACTION_NOTHING;
}
-
-
class TcpNormalizerFactory
{
public:
- static TcpNormalizer* create( StreamPolicy, TcpSession*, TcpTracker*, TcpTracker* );
+ static TcpNormalizer* create(TcpSession*, StreamPolicy, TcpTracker*, TcpTracker*);
};
#endif
#include "tcp_module.h"
#include "tcp_session.h"
-#include "tcp_events.h"
+#include "tcp_event_logger.h"
#include "tcp_normalizer.h"
#include "tcp_reassembler.h"
void TcpReassembler::trace_segments(void)
{
- TcpSegment* ss = seglist.head;
+ TcpSegmentNode* tsn = seglist.head;
uint32_t sx = tracker->r_win_base;
unsigned segs = 0, bytes = 0;
- while ( ss )
+ while ( tsn )
{
- if (SEQ_LT(sx, ss->seq))
- fprintf(stdout, " +%u", ss->seq - sx);
- else if (SEQ_GT(sx, ss->seq))
- fprintf(stdout, " -%u", sx - ss->seq);
+ if (SEQ_LT(sx, tsn->seq))
+ fprintf(stdout, " +%u", tsn->seq - sx);
+ else if (SEQ_GT(sx, tsn->seq))
+ fprintf(stdout, " -%u", sx - tsn->seq);
- fprintf(stdout, " %u", ss->payload_size);
+ fprintf(stdout, " %u", tsn->payload_size);
segs++;
- bytes += ss->payload_size;
+ bytes += tsn->payload_size;
- sx = ss->seq + ss->payload_size;
- ss = ss->next;
+ sx = tsn->seq + tsn->payload_size;
+ tsn = tsn->next;
}
assert(seg_count == segs);
assert(seg_bytes_logical == bytes);
uint32_t TcpReassembler::get_pending_segment_count(unsigned max)
{
uint32_t n = seg_count - flush_count;
- TcpSegment* ss;
+ TcpSegmentNode* tsn;
if ( !n || max == 1 )
return n;
n = 0;
- ss = seglist.head;
- while ( ss )
+ tsn = seglist.head;
+ while ( tsn )
{
- if ( !ss->buffered && SEQ_LT(ss->seq, tracker->r_win_base) )
+ if ( !tsn->buffered && SEQ_LT(tsn->seq, tracker->r_win_base) )
n++;
if ( max && n == max )
return n;
- ss = ss->next;
+ tsn = tsn->next;
}
return n;
return ( get_pending_segment_count(2) > 1 ); // FIXIT-L return false?
}
-int TcpReassembler::delete_reassembly_segment(TcpSegment* seg)
+int TcpReassembler::delete_reassembly_segment(TcpSegmentNode* tsn)
{
int ret;
- assert(seg);
+ assert(tsn);
- DebugFormat(DEBUG_STREAM_STATE, "Dropping segment at seq %X, len %d\n", seg->seq,
- seg->payload_size);
+ DebugFormat(DEBUG_STREAM_STATE, "Dropping segment at seq %X, len %d\n", tsn->seq,
+ tsn->payload_size);
- if (seg->prev)
- seg->prev->next = seg->next;
+ if (tsn->prev)
+ tsn->prev->next = tsn->next;
else
- seglist.head = seg->next;
+ seglist.head = tsn->next;
- if (seg->next)
- seg->next->prev = seg->prev;
+ if (tsn->next)
+ tsn->next->prev = tsn->prev;
else
- seglist.tail = seg->prev;
+ seglist.tail = tsn->prev;
- seg_bytes_logical -= seg->payload_size;
- seg_bytes_total -= seg->orig_dsize;
+ seg_bytes_logical -= tsn->payload_size;
+ seg_bytes_total -= tsn->orig_dsize;
- ret = seg->orig_dsize;
+ ret = tsn->orig_dsize;
- if (seg->buffered)
+ if (tsn->buffered)
{
tcpStats.segs_used++;
flush_count--;
}
- if (seglist.next == seg)
+ if (seglist.next == tsn)
seglist.next = NULL;
- seg->term( );
+ tsn->term( );
seg_count--;
return ret;
}
-int TcpReassembler::trim_delete_reassembly_segment(TcpSegment* seg, uint32_t flush_seq)
+int TcpReassembler::trim_delete_reassembly_segment(TcpSegmentNode* tsn, uint32_t flush_seq)
{
- if ( paf_active(&tracker->paf_state) && ( ( seg->seq + seg->payload_size ) > flush_seq ) )
+ if ( paf_active(&tracker->paf_state) && ( ( tsn->seq + tsn->payload_size ) > flush_seq ) )
{
- uint32_t delta = flush_seq - seg->seq;
+ uint32_t delta = flush_seq - tsn->seq;
- if (delta < seg->payload_size)
+ if (delta < tsn->payload_size)
{
DebugFormat(DEBUG_STREAM_STATE, "Left-Trimming segment at seq %X, len %d, delta %u\n",
- seg->seq, seg->payload_size, delta);
+ tsn->seq, tsn->payload_size, delta);
- seg->seq = flush_seq;
- seg->payload_size -= (uint16_t)delta;
+ tsn->seq = flush_seq;
+ tsn->payload_size -= (uint16_t)delta;
seg_bytes_logical -= delta;
return 0;
}
}
- return delete_reassembly_segment(seg);
+ return delete_reassembly_segment(tsn);
}
-void TcpReassembler::queue_reassembly_segment(TcpSegment* prev, TcpSegment* ss)
+void TcpReassembler::queue_reassembly_segment(TcpSegmentNode* prev, TcpSegmentNode* tsn)
{
- seglist.insert(prev, ss);
+ seglist.insert(prev, tsn);
seg_count++;
- seg_bytes_total += ss->orig_dsize;
+ seg_bytes_total += tsn->orig_dsize;
total_segs_queued++;
tcpStats.segs_queued++;
}
-bool TcpReassembler::is_segment_fasttrack(TcpSegment* tail, TcpDataBlock* tdb)
+bool TcpReassembler::is_segment_fasttrack(TcpSegmentNode* tail, TcpSegmentDescriptor& tsd)
{
- DebugFormat(DEBUG_STREAM_STATE, "Checking seq for fast track: %X > %X\n", tdb->seq,
+ DebugFormat(DEBUG_STREAM_STATE, "Checking seq for fast track: %X > %X\n", tsd.get_seq(),
tail->seq + tail->payload_size);
- if ( SEQ_EQ(tdb->seq, tail->seq + tail->payload_size) )
+ if ( SEQ_EQ(tsd.get_seq(), tail->seq + tail->payload_size) )
return true;
return false;
}
-int TcpReassembler::add_reassembly_segment(TcpDataBlock* tdb, int16_t len, uint32_t slide,
+int TcpReassembler::add_reassembly_segment(TcpSegmentDescriptor& tsd, int16_t len, uint32_t slide,
uint32_t trunc_len,
- uint32_t seq, TcpSegment* left)
+ uint32_t seq, TcpSegmentNode* left)
{
- TcpSegment* ss = nullptr;
+ TcpSegmentNode* tsn = nullptr;
int32_t newSize = len - slide - trunc_len;
if ( newSize <= 0 )
DebugFormat(DEBUG_STREAM_STATE, "zero size TCP data after left & right trimming "
"(len: %d slide: %d trunc: %d)\n", len, slide, trunc_len);
inc_tcp_discards();
- tracker->normalizer->trim_win_payload(tdb);
+ tracker->normalizer->trim_win_payload(tsd);
#ifdef DEBUG_STREAM_EX
{
- TcpSegment* idx = seglist.head;
+ TcpSegmentNode* idx = seglist.head;
unsigned long i = 0;
DebugFormat(DEBUG_STREAM_STATE, "Dumping seglist, %d segments\n", tracker->seg_count);
while (idx)
}
// FIXIT-L don't allocate overlapped part
- ss = TcpSegment::init(tdb->pkt->pkth->ts, tdb->pkt->data, tdb->pkt->dsize);
- if ( !ss )
+ tsn = TcpSegmentNode::init(tsd.get_pkt()->pkth->ts, tsd.get_pkt()->data, tsd.get_pkt()->dsize);
+ if ( !tsn )
return STREAM_INSERT_FAILED;
- else if ( TcpSegment::needs_pruning() )
+ else if ( TcpSegmentNode::needs_pruning() )
{
sfBase.iStreamFaults++;
- flow_con->prune_flows(PktType::TCP, tdb->pkt);
+ flow_con->prune_flows(PktType::TCP, tsd.get_pkt() );
}
- ss->payload = ss->data + slide;
- ss->payload_size = (uint16_t)newSize;
- ss->seq = seq;
- ss->ts = tdb->ts;
+ tsn->payload = tsn->data + slide;
+ tsn->payload_size = (uint16_t)newSize;
+ tsn->seq = seq;
+ tsn->ts = tsd.get_ts();
// FIXIT - The urgent ptr handling is broken... urg_offset is set here but currently
// not actually referenced anywhere else. In 2.9.7 the FlushStream function did reference
// this field but that code has been lost... urg ptr handling needs to be reviewed and fixed
- ss->urg_offset = tracker->normalizer->set_urg_offset(tdb->pkt->ptrs.tcph, tdb->pkt->dsize);
-
- queue_reassembly_segment(left, ss);
- seg_bytes_logical += ss->payload_size;
- total_bytes_queued += ss->payload_size;
- tdb->pkt->packet_flags |= PKT_STREAM_INSERT;
+ tsn->urg_offset = tracker->normalizer->set_urg_offset(tsd.get_tcph(), tsd.get_pkt()->dsize);
+ queue_reassembly_segment(left, tsn);
+ seg_bytes_logical += tsn->payload_size;
+ total_bytes_queued += tsn->payload_size;
+ tsd.get_pkt()->packet_flags |= PKT_STREAM_INSERT;
DebugFormat(DEBUG_STREAM_STATE,
"added %d bytes on segment list @ seq: 0x%X, total %lu, %d segments queued\n",
- ss->payload_size, ss->seq, seg_bytes_logical, get_pending_segment_count(0));
+ tsn->payload_size, tsn->seq, seg_bytes_logical, get_pending_segment_count(0));
#ifdef SEG_TEST
CheckSegments(tracker);
return STREAM_INSERT_OK;
}
-int TcpReassembler::dup_reassembly_segment(Packet* p, TcpSegment* left, TcpSegment** retSeg)
+int TcpReassembler::dup_reassembly_segment(Packet* p, TcpSegmentNode* left,
+ TcpSegmentNode** retSeg)
{
- TcpSegment* ss = TcpSegment::init(left->tv, left->payload, left->payload_size);
- if ( !ss )
+ TcpSegmentNode* tsn = TcpSegmentNode::init(left->tv, left->payload, left->payload_size);
+ if ( !tsn )
return STREAM_INSERT_FAILED;
- if ( TcpSegment::needs_pruning() )
+ if ( TcpSegmentNode::needs_pruning() )
{
sfBase.iStreamFaults++;
flow_con->prune_flows(PktType::TCP, p);
tcpStats.segs_split++;
// twiddle the values for overlaps
- ss->payload = ss->data;
- ss->payload_size = left->payload_size;
- ss->seq = left->seq;
+ tsn->payload = tsn->data;
+ tsn->payload_size = left->payload_size;
+ tsn->seq = left->seq;
- queue_reassembly_segment(left, ss);
+ queue_reassembly_segment(left, tsn);
DebugFormat(DEBUG_STREAM_STATE,
"added %d bytes on segment list @ seq: 0x%X, total %lu, %d segments queued\n",
- ss->payload_size, ss->seq, seg_bytes_logical, get_pending_segment_count(0));
+ tsn->payload_size, tsn->seq, seg_bytes_logical, get_pending_segment_count(0));
- *retSeg = ss;
+ *retSeg = tsn;
return STREAM_INSERT_OK;
}
int TcpReassembler::purge_to_seq(uint32_t flush_seq)
{
- TcpSegment* ss = nullptr;
- TcpSegment* dump_me = nullptr;
+ TcpSegmentNode* tsn = nullptr;
+ TcpSegmentNode* dump_me = nullptr;
int purged_bytes = 0;
uint32_t last_ts = 0;
return 0;
}
- ss = seglist.head;
+ tsn = seglist.head;
DebugFormat(DEBUG_STREAM_STATE, "In purge_to_seq, start seq = 0x%X end seq = 0x%X delta %d\n",
- ss->seq, flush_seq, flush_seq-ss->seq);
+ tsn->seq, flush_seq, flush_seq-tsn->seq);
- while ( ss )
+ while ( tsn )
{
- DebugFormat(DEBUG_STREAM_STATE, "s: %X sz: %d\n", ss->seq, ss->payload_size);
- dump_me = ss;
+ DebugFormat(DEBUG_STREAM_STATE, "s: %X sz: %d\n", tsn->seq, tsn->payload_size);
+ dump_me = tsn;
- ss = ss->next;
+ tsn = tsn->next;
if ( SEQ_LT(dump_me->seq, flush_seq) )
{
if (dump_me->ts > last_ts)
if ( !server_side )
{
- int32_t delta = last_ts - session->server.ts_last;
+ int32_t delta = last_ts - session->server->ts_last;
if ( delta > 0 )
- session->server.ts_last = last_ts;
+ session->server->ts_last = last_ts;
}
else
{
- int32_t delta = last_ts - session->client.ts_last;
+ int32_t delta = last_ts - session->client->ts_last;
if ( delta > 0 )
- session->client.ts_last = last_ts;
+ session->client->ts_last = last_ts;
}
return purged_bytes;
// purge_flushed_ackd():
// must only purge flushed and acked bytes we may flush partial segments
-// must adjust seq->seq and seg->size when a flush gets only the initial
+// must adjust seq->seq and tsn->size when a flush gets only the initial
// part of a segment
// * FIXIT-L need flag to mark any reassembled packets that have a gap
// (if we reassemble such)
int TcpReassembler::purge_flushed_ackd(void)
{
- TcpSegment* seg = seglist.head;
+ TcpSegmentNode* tsn = seglist.head;
uint32_t seq;
if (!seglist.head)
seq = seglist.head->seq;
- while ( seg && seg->buffered )
+ while ( tsn && tsn->buffered )
{
- uint32_t end = seg->seq + seg->payload_size;
+ uint32_t end = tsn->seq + tsn->payload_size;
if ( SEQ_GT(end, tracker->r_win_base) )
{
break;
}
seq = end;
- seg = seg->next;
+ tsn = tsn->next;
}
if ( seq != seglist.head->seq )
return purge_to_seq(seq);
void TcpReassembler::show_rebuilt_packet(Packet* pkt)
{
- if ( ( session->client.config->flags & STREAM_CONFIG_SHOW_PACKETS )
- || ( session->server.config->flags & STREAM_CONFIG_SHOW_PACKETS ) )
+ if ( ( session->config->flags & STREAM_CONFIG_SHOW_PACKETS )
+ || ( session->config->flags & STREAM_CONFIG_SHOW_PACKETS ) )
{
LogFlow(pkt);
LogNetData(pkt->data, pkt->dsize, pkt);
}
}
-uint32_t TcpReassembler::get_flush_data_len(TcpSegment* ss, uint32_t to_seq,
+uint32_t TcpReassembler::get_flush_data_len(TcpSegmentNode* tsn, uint32_t to_seq,
uint32_t flushBufSize)
{
- unsigned int flushSize = ss->payload_size;
+ unsigned int flushSize = tsn->payload_size;
// copy only till flush buffer gets full
if ( flushSize > flushBufSize )
flushSize = flushBufSize;
// copy only to flush point
- if ( paf_active(&tracker->paf_state) && SEQ_GT(ss->seq + flushSize, to_seq) )
- flushSize = to_seq - ss->seq;
+ if ( paf_active(&tracker->paf_state) && SEQ_GT(tsn->seq + flushSize, to_seq) )
+ flushSize = to_seq - tsn->seq;
return flushSize;
}
uint32_t total = toSeq - seglist.next->seq;
while ( SEQ_LT(seglist.next->seq, toSeq) )
{
- TcpSegment* ss = seglist.next, * sr = nullptr;
+ TcpSegmentNode* tsn = seglist.next, * sr = nullptr;
unsigned flushbuf_size = flushbuf_end - flushbuf;
- unsigned bytes_to_copy = get_flush_data_len(ss, toSeq, flushbuf_size);
+ unsigned bytes_to_copy = get_flush_data_len(tsn, toSeq, flushbuf_size);
unsigned bytes_copied = 0;
assert(bytes_to_copy);
- DebugFormat(DEBUG_STREAM_STATE, "Flushing %u bytes from %X\n", bytes_to_copy, ss->seq);
+ DebugFormat(DEBUG_STREAM_STATE, "Flushing %u bytes from %X\n", bytes_to_copy, tsn->seq);
- if ( !ss->next || ( bytes_to_copy < ss->payload_size ) || SEQ_EQ(ss->seq + bytes_to_copy,
+ if ( !tsn->next || ( bytes_to_copy < tsn->payload_size ) || SEQ_EQ(tsn->seq +
+ bytes_to_copy,
toSeq) )
flags |= PKT_PDU_TAIL;
const StreamBuffer* sb = tracker->splitter->reassemble(p->flow, total, bytes_flushed,
- ss->payload,
+ tsn->payload,
bytes_to_copy, flags, bytes_copied);
flags = 0;
if ( sb )
flushbuf += bytes_to_copy;
bytes_flushed += bytes_to_copy;
- if ( bytes_to_copy < ss->payload_size
- && dup_reassembly_segment(nullptr, ss, &sr) == STREAM_INSERT_OK )
+ if ( bytes_to_copy < tsn->payload_size
+ && dup_reassembly_segment(nullptr, tsn, &sr) == STREAM_INSERT_OK )
{
- ss->payload_size = bytes_to_copy;
+ tsn->payload_size = bytes_to_copy;
sr->seq += bytes_to_copy;
sr->payload_size -= bytes_to_copy;
sr->payload += bytes_to_copy;
}
- ss->buffered = true;
+ tsn->buffered = true;
flush_count++;
segs++;
if ( flushbuf >= flushbuf_end )
break;
- if ( SEQ_EQ(ss->seq + bytes_to_copy, toSeq) )
+ if ( SEQ_EQ(tsn->seq + bytes_to_copy, toSeq) )
break;
/* Check for a gap/missing packet */
// FIXIT-L PAF should account for missing data and resume
// scanning at the start of next PDU instead of aborting.
// FIXIT-L FIN may be in toSeq causing bogus gap counts.
- if (((ss->next && (ss->seq + ss->payload_size != ss->next->seq))
- || (!ss->next && (ss->seq + ss->payload_size < toSeq)))
+ if (((tsn->next && (tsn->seq + tsn->payload_size != tsn->next->seq))
+ || (!tsn->next && (tsn->seq + tsn->payload_size < toSeq)))
&& !(tracker->flags & TF_FIRST_PKT_MISSING))
{
- if ( ss->next )
- seglist.next = ss->next;
+ if ( tsn->next )
+ seglist.next = tsn->next;
tracker->flags |= TF_MISSING_PKT;
break;
}
- seglist.next = ss->next;
+ seglist.next = tsn->next;
if ( sb || !seglist.next )
break;
return _flush_to_seq(bytes, p, pkt_flags);
}
-/*
- * get the footprint for the current seglist, the difference
- * between our base sequence and the last ack'd sequence we
- * received
- */
+// FIXIT - the seq number math in the following 2 funcs does not handle wrapping
+// get the footprint for the current seglist, the difference between our
+// base sequence and the last ack'd sequence we received
uint32_t TcpReassembler::get_q_footprint(void)
{
- uint32_t fp;
+ int32_t fp;
if ( tracker == nullptr )
return 0;
fp = tracker->r_win_base - seglist_base_seq;
-
if ( fp <= 0 )
return 0;
// to avoid the while loop, etc. below.
uint32_t TcpReassembler::get_q_sequenced(void)
{
- uint32_t len;
- TcpSegment* seg = tracker ? seglist.head : nullptr;
- TcpSegment* base = nullptr;
+ int32_t len;
+ TcpSegmentNode* tsn = tracker ? seglist.head : nullptr;
+ TcpSegmentNode* base = nullptr;
- if ( !seg )
+ if ( !tsn )
return 0;
- if ( session->flow->two_way_traffic() && SEQ_LT(tracker->r_win_base, seg->seq) )
+ if ( session->flow->two_way_traffic() && SEQ_LT(tracker->r_win_base, tsn->seq) )
return 0;
- while ( seg->next && ( seg->next->seq == seg->seq + seg->payload_size ) )
+ while ( tsn->next && ( tsn->next->seq == tsn->seq + tsn->payload_size ) )
{
- if ( !seg->buffered && !base )
- base = seg;
- seg = seg->next;
+ if ( !tsn->buffered && !base )
+ base = tsn;
+ tsn = tsn->next;
}
- if ( !seg->buffered && !base )
- base = seg;
+ if ( !tsn->buffered && !base )
+ base = tsn;
if ( !base )
return 0;
seglist.next = base;
seglist_base_seq = base->seq;
- len = seg->seq + seg->payload_size - base->seq;
+ len = tsn->seq + tsn->payload_size - base->seq;
return ( len > 0 ) ? len : 0;
}
Profile profile(s5TcpPAFPerfStats);
uint32_t total = 0, avail;
- TcpSegment* seg;
+ TcpSegmentNode* tsn;
avail = get_q_sequenced( );
- seg = seglist.next;
+ tsn = seglist.next;
// * must stop if gap (checked in paf_check)
- while ( seg && *flags && ( total < avail ) )
+ while ( tsn && *flags && ( total < avail ) )
{
int32_t flush_pt;
- uint32_t size = seg->payload_size;
- uint32_t end = seg->seq + seg->payload_size;
+ uint32_t size = tsn->payload_size;
+ uint32_t end = tsn->seq + tsn->payload_size;
uint32_t pos = paf_position(&tracker->paf_state);
total += size;
if ( paf_initialized(&tracker->paf_state) && SEQ_LEQ(end, pos) )
{
- seg = seg->next;
+ tsn = tsn->next;
continue;
}
flush_pt = paf_check(tracker->splitter, &tracker->paf_state, session->flow,
- seg->payload, size, total, seg->seq, flags);
+ tsn->payload, size, total, tsn->seq, flags);
if (flush_pt >= 0)
{
}
return flush_pt;
}
- seg = seg->next;
+ tsn = tsn->next;
}
return -1;
bool c2s = tracker->splitter->to_server();
delete tracker->splitter;
- tracker->splitter = new AtomSplitter(c2s, tracker->config->paf_max);
+ tracker->splitter = new AtomSplitter(c2s, session->config->paf_max);
tracker->paf_state.paf = StreamSplitter::SEARCH;
}
Profile profile(s5TcpPAFPerfStats);
uint32_t total = 0;
- TcpSegment* seg = SEQ_LT(seglist_base_seq, tracker->r_win_base) ? seglist.head : nullptr;
+ TcpSegmentNode* tsn = SEQ_LT(seglist_base_seq, tracker->r_win_base) ? seglist.head : nullptr;
// must stop if not acked
- // must use adjusted size of seg if not fully acked
+ // must use adjusted size of tsn if not fully acked
// must stop if gap (checked in paf_check)
- while (seg && *flags && SEQ_LT(seg->seq, tracker->r_win_base))
+ while (tsn && *flags && SEQ_LT(tsn->seq, tracker->r_win_base))
{
int32_t flush_pt;
- uint32_t size = seg->payload_size;
- uint32_t end = seg->seq + seg->payload_size;
+ uint32_t size = tsn->payload_size;
+ uint32_t end = tsn->seq + tsn->payload_size;
uint32_t pos = paf_position(&tracker->paf_state);
if ( paf_initialized(&tracker->paf_state) && SEQ_LEQ(end, pos) )
{
total += size;
- seg = seg->next;
+ tsn = tsn->next;
continue;
}
if ( SEQ_GT(end, tracker->r_win_base))
- size = tracker->r_win_base - seg->seq;
+ size = tracker->r_win_base - tsn->seq;
total += size;
flush_pt = paf_check(tracker->splitter, &tracker->paf_state, session->flow,
- seg->payload, size, total, seg->seq, flags);
+ tsn->payload, size, total, tsn->seq, flags);
if ( flush_pt >= 0 )
{
}
return flush_pt;
}
- seg = seg->next;
+ tsn = tsn->next;
}
return -1;
// if this payload is exactly one pdu, don't
// actually flush, just use the raw packet
if ( listener->seglist.next &&
- ( tdb->seq == listener->seglist.next->seq ) &&
+ ( tsd.seq == listener->seglist.next->seq ) &&
( flush_amt == listener->seglist.next->payload_size ) &&
( flush_amt == p->dsize ) )
{
flags = get_reverse_packet_dir(p);
flush_amt = flush_pdu_ackd(&flags);
}
+
if (!flags && tracker->splitter->is_paf())
{
fallback( );
seg_bytes_logical = 0;
}
-void TcpReassembler::insert_segment_in_empty_seglist(TcpDataBlock* tdb)
+void TcpReassembler::insert_segment_in_empty_seglist(TcpSegmentDescriptor& tsd)
{
- const tcp::TCPHdr* tcph = tdb->pkt->ptrs.tcph;
+ const tcp::TCPHdr* tcph = tsd.get_tcph();
uint32_t overlap = 0;
- uint32_t seq = tdb->seq;
+ uint32_t seq = tsd.get_seq();
if ( tcph->is_syn() )
seq++;
if ( SEQ_GT(tracker->r_win_base, seq) )
{
DebugMessage(DEBUG_STREAM_STATE, "segment overlaps ack'd data...\n");
- overlap = tracker->r_win_base - tdb->seq;
- if ( overlap >= tdb->pkt->dsize )
+ overlap = tracker->r_win_base - tsd.get_seq();
+ if ( overlap >= tsd.get_pkt()->dsize )
{
DebugMessage(DEBUG_STREAM_STATE, "full overlap on ack'd data, dropping segment\n");
return;
}
// BLOCK add new block to seglist containing data
- add_reassembly_segment(tdb, tdb->pkt->dsize, overlap, 0, tdb->seq + overlap, NULL);
+ add_reassembly_segment(tsd, tsd.get_pkt()->dsize, overlap, 0, tsd.get_seq() + overlap, NULL);
DebugFormat(DEBUG_STREAM_STATE,
"Attached new queue to seglist, %d bytes queued, base_seq 0x%X\n",
- tdb->pkt->dsize-overlap, seglist_base_seq);
+ tsd.get_pkt()->dsize - overlap, seglist_base_seq);
}
-void TcpReassembler::init_overlap_editor(TcpDataBlock* tdb)
+void TcpReassembler::init_overlap_editor(TcpSegmentDescriptor& tsd)
{
- TcpSegment* left = nullptr;
- TcpSegment* right = nullptr;
- TcpSegment* ss = nullptr;
+ TcpSegmentNode* left = nullptr;
+ TcpSegmentNode* right = nullptr;
+ TcpSegmentNode* tsn = nullptr;
int32_t dist_head;
int32_t dist_tail;
DEBUG_WRAP(
- TcpSegment *lastptr = NULL;
+ TcpSegmentNode *lastptr = NULL;
uint32_t base_seq = seglist_base_seq;
int last = 0;
);
if ( seglist.head && seglist.tail )
{
- if ( SEQ_GT(tdb->seq, seglist.head->seq) )
- dist_head = tdb->seq - seglist.head->seq;
+ if ( SEQ_GT(tsd.get_seq(), seglist.head->seq) )
+ dist_head = tsd.get_seq() - seglist.head->seq;
else
- dist_head = seglist.head->seq - tdb->seq;
+ dist_head = seglist.head->seq - tsd.get_seq();
- if ( SEQ_GT(tdb->seq, seglist.tail->seq) )
- dist_tail = tdb->seq - seglist.tail->seq;
+ if ( SEQ_GT(tsd.get_seq(), seglist.tail->seq) )
+ dist_tail = tsd.get_seq() - seglist.tail->seq;
else
- dist_tail = seglist.tail->seq - tdb->seq;
+ dist_tail = seglist.tail->seq - tsd.get_seq();
}
else
dist_head = dist_tail = 0;
if ( SEQ_LEQ(dist_head, dist_tail) )
{
- for ( ss = seglist.head; ss; ss = ss->next )
+ for ( tsn = seglist.head; tsn; tsn = tsn->next )
{
DEBUG_WRAP(
- DebugFormat(DEBUG_STREAM_STATE, "ss: %p seq: 0x%X size: %lu delta: %d\n",
- ss, ss->seq, ss->payload_size, ( ss->seq - base_seq ) - last);
- last = ss->seq - base_seq;
- lastptr = ss;
+ DebugFormat(DEBUG_STREAM_STATE, "tsn: %p seq: 0x%X size: %lu delta: %d\n",
+ tsn, tsn->seq, tsn->payload_size, ( tsn->seq - base_seq ) - last);
+ last = tsn->seq - base_seq;
+ lastptr = tsn;
- DebugFormat(DEBUG_STREAM_STATE, " lastptr: %p ss->next: %p ss->prev: %p\n",
- lastptr, ss->next, ss->prev);
+ DebugFormat(DEBUG_STREAM_STATE, " lastptr: %p tsn->next: %p tsn->prev: %p\n",
+ lastptr, tsn->next, tsn->prev);
);
- right = ss;
- if ( SEQ_GEQ(right->seq, tdb->seq) )
+ right = tsn;
+ if ( SEQ_GEQ(right->seq, tsd.get_seq() ) )
break;
left = right;
}
- if ( ss == nullptr )
+ if ( tsn == nullptr )
right = nullptr;
}
else
{
- for ( ss = seglist.tail; ss; ss = ss->prev )
+ for ( tsn = seglist.tail; tsn; tsn = tsn->prev )
{
DEBUG_WRAP(
- DebugFormat(DEBUG_STREAM_STATE, "ss: %p seq: 0x%X size: %lu delta: %d\n",
- ss, ss->seq, ss->payload_size, ( ss->seq - base_seq ) - last);
- last = ss->seq - base_seq;
- lastptr = ss;
+ DebugFormat(DEBUG_STREAM_STATE, "tsn: %p seq: 0x%X size: %lu delta: %d\n",
+ tsn, tsn->seq, tsn->payload_size, ( tsn->seq - base_seq ) - last);
+ last = tsn->seq - base_seq;
+ lastptr = tsn;
- DebugFormat(DEBUG_STREAM_STATE, " lastptr: %p ss->next: %p ss->prev: %p\n",
- lastptr, ss->next, ss->prev);
+ DebugFormat(DEBUG_STREAM_STATE, " lastptr: %p tsn->next: %p tsn->prev: %p\n",
+ lastptr, tsn->next, tsn->prev);
);
- left = ss;
- if ( SEQ_LT(left->seq, tdb->seq) )
+ left = tsn;
+ if ( SEQ_LT(left->seq, tsd.get_seq() ) )
break;
right = left;
}
- if (ss == nullptr)
+ if (tsn == nullptr)
left = nullptr;
}
DebugFormat(DEBUG_STREAM_STATE, "left: %p:0x%X right: %p:0x%X\n",
left, left ? left->seq : 0, right, right ? right->seq : 0);
- init_soe(tdb, left, right);
+ init_soe(tsd, left, right);
}
-int TcpReassembler::insert_segment_in_seglist(TcpDataBlock* tdb)
+int TcpReassembler::insert_segment_in_seglist(TcpSegmentDescriptor& tsd)
{
int rc = STREAM_INSERT_OK;
DebugFormat(DEBUG_STREAM_STATE,
"Queuing %d bytes on stream!\nbase_seq: %X seq: %X seq_end: %X\n",
- tdb->end_seq - tdb->seq, seglist_base_seq, tdb->seq, tdb->end_seq);
+ tsd.get_end_seq() - tsd.get_seq(), seglist_base_seq, tsd.get_seq(), tsd.get_end_seq());
DebugFormat(DEBUG_STREAM_STATE, "%d segments on seglist\n", get_pending_segment_count(0));
DebugMessage(DEBUG_STREAM_STATE, "!+!+!+!+!+!+!+!+!+!+!+!+!+!+!+!+!+!+!+!+!+!+!+!+!+!+!+\n");
DebugMessage(DEBUG_STREAM_STATE, "!+!+!+!+!+!+!+!+!+!+!+!+!+!+!+!+!+!+!+!+!+!+!+!+!+!+!+\n");
// NORM fast tracks are in sequence - no norms
- if ( seglist.tail && is_segment_fasttrack(seglist.tail, tdb) )
+ if ( seglist.tail && is_segment_fasttrack(seglist.tail, tsd) )
{
/* segment fit cleanly at the end of the segment list */
- TcpSegment* left = seglist.tail;
+ TcpSegmentNode* left = seglist.tail;
DebugFormat(DEBUG_STREAM_STATE, "Fast tracking segment! (tail_seq %X size %d)\n",
seglist.tail->seq, seglist.tail->payload_size);
// BLOCK add to existing block and/or allocate new block
- rc = add_reassembly_segment(tdb, tdb->pkt->dsize, 0, 0, tdb->seq, left);
+ rc = add_reassembly_segment(tsd, tsd.get_pkt()->dsize, 0, 0, tsd.get_seq(), left);
return rc;
}
- init_overlap_editor(tdb);
+ init_overlap_editor(tsd);
rc = eval_left();
if ( rc != STREAM_INSERT_OK )
return rc;
if ( keep_segment )
{
/* Adjust slide so that is correct relative to orig seq */
- slide = seq - tdb->seq;
- rc = add_reassembly_segment(tdb, len, slide, trunc_len, seq, left);
+ slide = seq - tsd.get_seq();
+ rc = add_reassembly_segment(tsd, len, slide, trunc_len, seq, left);
}
else
{
return rc;
}
-int TcpReassembler::queue_packet_for_reassembly(TcpDataBlock* tdb)
+int TcpReassembler::queue_packet_for_reassembly(TcpSegmentDescriptor& tsd)
{
Profile profile(s5TcpInsertPerfStats);
if ( seg_count == 0 )
{
- insert_segment_in_empty_seglist(tdb);
+ insert_segment_in_empty_seglist(tsd);
return STREAM_INSERT_OK;
}
- if ( SEQ_GT(tracker->r_win_base, tdb->seq) )
+ if ( SEQ_GT(tracker->r_win_base, tsd.get_seq() ) )
{
- uint32_t offset = tracker->r_win_base - tdb->seq;
+ uint32_t offset = tracker->r_win_base - tsd.get_seq();
- if ( offset < tdb->pkt->dsize )
+ if ( offset < tsd.get_pkt()->dsize )
{
- tdb->seq += offset;
- tdb->pkt->data += offset;
- tdb->pkt->dsize -= (uint16_t)offset;
+ tsd.set_seq(tsd.get_seq() + offset);
+ tsd.get_pkt()->data += offset;
+ tsd.get_pkt()->dsize -= (uint16_t)offset;
- rc = insert_segment_in_seglist(tdb);
+ rc = insert_segment_in_seglist(tsd);
- tdb->pkt->dsize += (uint16_t)offset;
- tdb->pkt->data -= offset;
- tdb->seq -= offset;
+ tsd.get_pkt()->dsize += (uint16_t)offset;
+ tsd.get_pkt()->data -= offset;
+ tsd.set_seq(tsd.get_seq() - offset);
}
}
else
- rc = insert_segment_in_seglist(tdb);
+ rc = insert_segment_in_seglist(tsd);
return rc;
}
#ifdef SEG_TEST
static void CheckSegments(const TcpTracker* a)
{
- TcpSegment* ss = a->seglist.head;
- uint32_t sx = ss ? ss->seq : 0;
+ TcpSegmentNode* tsn = a->seglist.head;
+ uint32_t sx = tsn ? tsn->seq : 0;
- while ( ss )
+ while ( tsn )
{
- if ( SEQ_GT(sx, ss->seq) )
+ if ( SEQ_GT(sx, tsn->seq) )
{
const int SEGBORK = 0;
assert(SEGBORK);
}
- sx = ss->seq + ss->payload_size;
- ss = ss->next;
+ sx = tsn->seq + tsn->payload_size;
+ tsn = tsn->next;
}
}
#include "stream/stream_api.h"
#include "segment_overlap_editor.h"
-#include "tcp_segment.h"
#include "tcp_defs.h"
+#include "tcp_segment_node.h"
class TcpSession;
struct TcpTracker;
class TcpReassembler : public SegmentOverlapEditor
{
public:
- virtual ~TcpReassembler() { }
-
- virtual int add_reassembly_segment(TcpDataBlock*, int16_t len, uint32_t slide, uint32_t trunc, uint32_t seq,
- TcpSegment *left) override;
- int dup_reassembly_segment(Packet *p, TcpSegment *left, TcpSegment **retSeg) override;
- int delete_reassembly_segment( TcpSegment* seg ) override;
-
- void set_tcp_reassembly_policy( StreamPolicy os_policy );
- virtual int queue_packet_for_reassembly( TcpDataBlock * );
- virtual void insert_segment_in_empty_seglist( TcpDataBlock *tdb );
- virtual int insert_segment_in_seglist( TcpDataBlock* tdb );
- virtual void purge_segment_list( void );
- virtual int flush_stream( Packet *p, uint32_t dir);
- virtual int purge_flushed_ackd( void );
- virtual void flush_queued_segments(Flow* flow, bool clear, Packet* p = nullptr);
- virtual bool is_segment_pending_flush( void );
- virtual uint32_t get_pending_segment_count( unsigned max );
- virtual int flush_on_data_policy( Packet* );
- virtual int flush_on_ack_policy( Packet* );
- void trace_segments( void );
+ virtual ~TcpReassembler() { }
+ virtual int queue_packet_for_reassembly(TcpSegmentDescriptor&);
+ virtual void purge_segment_list(void);
+ virtual int flush_stream(Packet* p, uint32_t dir);
+ virtual int purge_flushed_ackd(void);
+ virtual void flush_queued_segments(Flow* flow, bool clear, Packet* p = nullptr);
+ virtual bool is_segment_pending_flush(void);
+ virtual int flush_on_data_policy(Packet*);
+ virtual int flush_on_ack_policy(Packet*);
void set_seglist_base_seq(uint32_t seglist_base_seq)
{
this->seglist_base_seq = seglist_base_seq;
- DebugFormat(DEBUG_STREAM_STATE, "seglist_base_seq = %X\n", seglist_base_seq );
+ DebugFormat(DEBUG_STREAM_STATE, "seglist_base_seq = %X\n", seglist_base_seq);
}
uint32_t get_seglist_base_seq() const
return reassembly_policy;
}
- int purge_to_seq( uint32_t flush_seq );
+ void trace_segments(void);
protected:
bool server_side;
uint32_t flush_count; /* number of flushed queued segments */
uint32_t xtradata_mask; /* extra data available to log */
- TcpReassembler( TcpSession* session, TcpTracker* tracker, StreamPolicy os_policy, bool server ) :
- server_side( server ), tracker(tracker), flush_count( 0 ), xtradata_mask( 0 )
+ TcpReassembler(TcpSession* session, TcpTracker* tracker, StreamPolicy os_policy, bool server) :
+ server_side(server), tracker(tracker), flush_count(0), xtradata_mask(0)
{
this->session = session;
- set_tcp_reassembly_policy( os_policy );
+ set_tcp_reassembly_policy(os_policy);
- if( server_side )
+ if ( server_side )
{
ignore_dir = SSN_DIR_FROM_CLIENT;
packet_dir = PKT_FROM_CLIENT;
seglist.next = nullptr;
}
- bool flush_data_ready( void );
- int trim_delete_reassembly_segment( TcpSegment* seg, uint32_t flush_seq);
- void queue_reassembly_segment(TcpSegment *prev, TcpSegment *ss);
- void init_overlap_editor( TcpDataBlock* tdb );
- bool is_segment_fasttrack(TcpSegment *tail, TcpDataBlock *tdb);
- int purge_alerts( uint32_t /*flush_seq*/, Flow* flow);
- void show_rebuilt_packet( Packet* pkt );
- uint32_t get_flush_data_len( TcpSegment *ss, uint32_t to_seq, uint32_t flushBufSize);
- int flush_data_segments(Packet* p, uint32_t toSeq, uint8_t *flushbuf, const uint8_t *flushbuf_end);
+ int add_reassembly_segment(TcpSegmentDescriptor&, int16_t len, uint32_t slide, uint32_t trunc,
+ uint32_t seq, TcpSegmentNode* left) override;
+ int dup_reassembly_segment(Packet* p, TcpSegmentNode* left, TcpSegmentNode** retSeg) override;
+ int delete_reassembly_segment(TcpSegmentNode* seg) override;
+
+ virtual void insert_segment_in_empty_seglist(TcpSegmentDescriptor&);
+ virtual int insert_segment_in_seglist(TcpSegmentDescriptor&);
+
+ void set_tcp_reassembly_policy(StreamPolicy os_policy);
+ virtual uint32_t get_pending_segment_count(unsigned max);
+
+ bool flush_data_ready(void);
+ int trim_delete_reassembly_segment(TcpSegmentNode* seg, uint32_t flush_seq);
+ void queue_reassembly_segment(TcpSegmentNode* prev, TcpSegmentNode* ss);
+ void init_overlap_editor(TcpSegmentDescriptor&);
+ bool is_segment_fasttrack(TcpSegmentNode* tail, TcpSegmentDescriptor&);
+ int purge_alerts(uint32_t /*flush_seq*/, Flow* flow);
+ void show_rebuilt_packet(Packet* pkt);
+ uint32_t get_flush_data_len(TcpSegmentNode* ss, uint32_t to_seq, uint32_t flushBufSize);
+ int flush_data_segments(Packet* p, uint32_t toSeq, uint8_t* flushbuf, const
+ uint8_t* flushbuf_end);
void prep_s5_pkt(Flow* flow, Packet* p, uint32_t pkt_flags);
- int _flush_to_seq( uint32_t bytes, Packet *p, uint32_t pkt_flags );
- int flush_to_seq( uint32_t bytes, Packet *p, uint32_t pkt_flags );
- uint32_t get_q_footprint( void );
- uint32_t get_q_sequenced( void );
+ int _flush_to_seq(uint32_t bytes, Packet* p, uint32_t pkt_flags);
+ int flush_to_seq(uint32_t bytes, Packet* p, uint32_t pkt_flags);
+ uint32_t get_q_footprint(void);
+ uint32_t get_q_sequenced(void);
void final_flush(Packet* p, PegCount& peg, uint32_t dir);
uint32_t get_reverse_packet_dir(const Packet* p);
uint32_t get_forward_packet_dir(const Packet* p);
- uint32_t flush_pdu_ips( uint32_t* flags );
- void fallback( void );
- uint32_t flush_pdu_ackd( uint32_t* flags );
+ uint32_t flush_pdu_ips(uint32_t* flags);
+ void fallback(void);
+ uint32_t flush_pdu_ackd(uint32_t* flags);
+ int purge_to_seq(uint32_t flush_seq);
};
#endif
+
// Created on: Oct 9, 2015
#include "tcp_module.h"
-#include "tcp_events.h"
+#include "tcp_event_logger.h"
#include "tcp_session.h"
#include "tcp_reassemblers.h"
class TcpReassemblerFirst : public TcpReassembler
{
public:
- TcpReassemblerFirst( TcpSession* session, TcpTracker* tracker, bool server ) :
- TcpReassembler( session, tracker, StreamPolicy::OS_FIRST, server )
- { }
+ TcpReassemblerFirst(TcpSession* session, TcpTracker* tracker, bool server) :
+ TcpReassembler(session, tracker, StreamPolicy::OS_FIRST, server)
+ { }
private:
int insert_left_overlap(void) override
class TcpReassemblerLast : public TcpReassembler
{
public:
- TcpReassemblerLast( TcpSession* session, TcpTracker* tracker, bool server ) :
- TcpReassembler( session, tracker, StreamPolicy::OS_LAST, server )
- { }
+ TcpReassemblerLast(TcpSession* session, TcpTracker* tracker, bool server) :
+ TcpReassembler(session, tracker, StreamPolicy::OS_LAST, server)
+ { }
private:
int insert_left_overlap(void) override
class TcpReassemblerLinux : public TcpReassembler
{
public:
- TcpReassemblerLinux( TcpSession* session, TcpTracker* tracker, bool server ) :
- TcpReassembler( session, tracker, StreamPolicy::OS_LINUX, server )
- { }
+ TcpReassemblerLinux(TcpSession* session, TcpTracker* tracker, bool server) :
+ TcpReassembler(session, tracker, StreamPolicy::OS_LINUX, server)
+ { }
private:
int insert_left_overlap(void) override
class TcpReassemblerOldLinux : public TcpReassembler
{
public:
- TcpReassemblerOldLinux( TcpSession* session, TcpTracker* tracker, bool server ) :
- TcpReassembler( session, tracker, StreamPolicy::OS_OLD_LINUX, server )
- { }
+ TcpReassemblerOldLinux(TcpSession* session, TcpTracker* tracker, bool server) :
+ TcpReassembler(session, tracker, StreamPolicy::OS_OLD_LINUX, server)
+ { }
private:
int insert_left_overlap(void) override
class TcpReassemblerBSD : public TcpReassembler
{
public:
- TcpReassemblerBSD( TcpSession* session, TcpTracker* tracker, bool server ) :
- TcpReassembler( session, tracker, StreamPolicy::OS_BSD, server )
- { }
+ TcpReassemblerBSD(TcpSession* session, TcpTracker* tracker, bool server) :
+ TcpReassembler(session, tracker, StreamPolicy::OS_BSD, server)
+ { }
private:
int insert_left_overlap(void) override
class TcpReassemblerMacOS : public TcpReassembler
{
public:
- TcpReassemblerMacOS( TcpSession* session, TcpTracker* tracker, bool server ) :
- TcpReassembler( session, tracker, StreamPolicy::OS_MACOS, server )
- { }
+ TcpReassemblerMacOS(TcpSession* session, TcpTracker* tracker, bool server) :
+ TcpReassembler(session, tracker, StreamPolicy::OS_MACOS, server)
+ { }
private:
int insert_left_overlap(void) override
class TcpReassemblerSolaris : public TcpReassembler
{
public:
- TcpReassemblerSolaris( TcpSession* session, TcpTracker* tracker, bool server ) :
- TcpReassembler( session, tracker, StreamPolicy::OS_SOLARIS, server )
- { }
+ TcpReassemblerSolaris(TcpSession* session, TcpTracker* tracker, bool server) :
+ TcpReassembler(session, tracker, StreamPolicy::OS_SOLARIS, server)
+ { }
private:
int insert_left_overlap(void) override
class TcpReassemblerIrix : public TcpReassembler
{
public:
- TcpReassemblerIrix( TcpSession* session, TcpTracker* tracker, bool server ) :
- TcpReassembler( session, tracker, StreamPolicy::OS_IRIX, server )
- { }
+ TcpReassemblerIrix(TcpSession* session, TcpTracker* tracker, bool server) :
+ TcpReassembler(session, tracker, StreamPolicy::OS_IRIX, server)
+ { }
private:
int insert_left_overlap(void) override
{
return full_right_overlap_os2( );
}
-
};
class TcpReassemblerHpux11 : public TcpReassembler
{
public:
- TcpReassemblerHpux11( TcpSession* session, TcpTracker* tracker, bool server ) :
- TcpReassembler( session, tracker, StreamPolicy::OS_HPUX11, server )
- { }
+ TcpReassemblerHpux11(TcpSession* session, TcpTracker* tracker, bool server) :
+ TcpReassembler(session, tracker, StreamPolicy::OS_HPUX11, server)
+ { }
private:
int insert_left_overlap(void) override
class TcpReassemblerHpux10 : public TcpReassembler
{
public:
- TcpReassemblerHpux10( TcpSession* session, TcpTracker* tracker, bool server ) :
- TcpReassembler( session, tracker, StreamPolicy::OS_HPUX10, server )
- { }
+ TcpReassemblerHpux10(TcpSession* session, TcpTracker* tracker, bool server) :
+ TcpReassembler(session, tracker, StreamPolicy::OS_HPUX10, server)
+ { }
private:
int insert_left_overlap(void) override
- {
+ {
return left_overlap_keep_first( );
- }
+ }
void insert_right_overlap(void) override
- {
+ {
right_overlap_truncate_existing( );
- }
+ }
int insert_full_overlap(void) override
- {
+ {
return full_right_overlap_os2( );
- }
+ }
};
class TcpReassemblerWindows : public TcpReassembler
{
public:
- TcpReassemblerWindows( TcpSession* session, TcpTracker* tracker, bool server ) :
- TcpReassembler( session, tracker, StreamPolicy::OS_WINDOWS, server )
- { }
+ TcpReassemblerWindows(TcpSession* session, TcpTracker* tracker, bool server) :
+ TcpReassembler(session, tracker, StreamPolicy::OS_WINDOWS, server)
+ { }
private:
int insert_left_overlap(void) override
- {
- return left_overlap_keep_first( );
- }
-
- void insert_right_overlap(void) override
- {
- right_overlap_truncate_existing( );
- }
-
- int insert_full_overlap(void) override
- {
- return full_right_overlap_os1( );
- }
+ {
+ return left_overlap_keep_first( );
+ }
+
+ void insert_right_overlap(void) override
+ {
+ right_overlap_truncate_existing( );
+ }
+
+ int insert_full_overlap(void) override
+ {
+ return full_right_overlap_os1( );
+ }
};
class TcpReassemblerWindows2K3 : public TcpReassembler
{
public:
- TcpReassemblerWindows2K3( TcpSession* session, TcpTracker* tracker, bool server) :
- TcpReassembler( session, tracker, StreamPolicy::OS_WINDOWS2K3, server )
- { }
+ TcpReassemblerWindows2K3(TcpSession* session, TcpTracker* tracker, bool server) :
+ TcpReassembler(session, tracker, StreamPolicy::OS_WINDOWS2K3, server)
+ { }
private:
int insert_left_overlap(void) override
class TcpReassemblerVista : public TcpReassembler
{
public:
- TcpReassemblerVista( TcpSession* session, TcpTracker* tracker, bool server ) :
- TcpReassembler( session, tracker, StreamPolicy::OS_VISTA, server )
- { }
+ TcpReassemblerVista(TcpSession* session, TcpTracker* tracker, bool server) :
+ TcpReassembler(session, tracker, StreamPolicy::OS_VISTA, server)
+ { }
private:
int insert_left_overlap(void) override
class TcpReassemblerProxy : public TcpReassemblerFirst
{
public:
- TcpReassemblerProxy( TcpSession* session, TcpTracker* tracker, bool server ) :
- TcpReassemblerFirst( session, tracker, server )
+ TcpReassemblerProxy(TcpSession* session, TcpTracker* tracker, bool server) :
+ TcpReassemblerFirst(session, tracker, server)
{
tcp_ips_data = NORM_MODE_OFF;
}
}
};
-TcpReassembler* TcpReassemblerFactory::create( TcpSession* session, TcpTracker* tracker,
- StreamPolicy os_policy, bool server )
+TcpReassembler* TcpReassemblerFactory::create(TcpSession* session, TcpTracker* tracker,
+ StreamPolicy os_policy, bool server)
{
NormMode tcp_ips_data = Normalize_GetMode(NORM_TCP_IPS);
if (tcp_ips_data == NORM_MODE_ON)
- return new TcpReassemblerFirst( session, tracker, server );
+ return new TcpReassemblerFirst(session, tracker, server);
else
{
switch (os_policy)
{
case StreamPolicy::OS_FIRST:
- return new TcpReassemblerFirst( session, tracker, server );
+ return new TcpReassemblerFirst(session, tracker, server);
break;
case StreamPolicy::OS_LAST:
- return new TcpReassemblerLast( session, tracker, server );
+ return new TcpReassemblerLast(session, tracker, server);
break;
case StreamPolicy::OS_LINUX:
- return new TcpReassemblerLinux( session, tracker, server );
+ return new TcpReassemblerLinux(session, tracker, server);
break;
case StreamPolicy::OS_OLD_LINUX:
- return new TcpReassemblerOldLinux( session, tracker, server );
+ return new TcpReassemblerOldLinux(session, tracker, server);
break;
case StreamPolicy::OS_BSD:
- return new TcpReassemblerBSD( session, tracker, server );
+ return new TcpReassemblerBSD(session, tracker, server);
break;
case StreamPolicy::OS_MACOS:
- return new TcpReassemblerMacOS( session, tracker, server );
+ return new TcpReassemblerMacOS(session, tracker, server);
break;
case StreamPolicy::OS_SOLARIS:
- return new TcpReassemblerSolaris( session, tracker, server );
+ return new TcpReassemblerSolaris(session, tracker, server);
break;
case StreamPolicy::OS_IRIX:
- return new TcpReassemblerIrix( session, tracker, server );
+ return new TcpReassemblerIrix(session, tracker, server);
break;
case StreamPolicy::OS_HPUX11:
- return new TcpReassemblerHpux11( session, tracker, server );
+ return new TcpReassemblerHpux11(session, tracker, server);
break;
case StreamPolicy::OS_HPUX10:
- return new TcpReassemblerHpux10( session, tracker, server );
+ return new TcpReassemblerHpux10(session, tracker, server);
break;
case StreamPolicy::OS_WINDOWS:
- return new TcpReassemblerWindows( session, tracker, server );
+ return new TcpReassemblerWindows(session, tracker, server);
break;
case StreamPolicy::OS_WINDOWS2K3:
- return new TcpReassemblerWindows2K3( session, tracker, server );
+ return new TcpReassemblerWindows2K3(session, tracker, server);
break;
case StreamPolicy::OS_VISTA:
- return new TcpReassemblerVista( session, tracker, server );
+ return new TcpReassemblerVista(session, tracker, server);
break;
case StreamPolicy::OS_PROXY:
- return new TcpReassemblerProxy( session, tracker, server );
+ return new TcpReassemblerProxy(session, tracker, server);
break;
default:
- return new TcpReassemblerBSD( session, tracker, server );
+ return new TcpReassemblerBSD(session, tracker, server);
break;
}
-
}
}
class TcpReassemblerFactory
{
public:
- static TcpReassembler* create( TcpSession* session, TcpTracker* tracker,
- StreamPolicy os_policy, bool server );
+ static TcpReassembler* create(TcpSession* session, TcpTracker* tracker,
+ StreamPolicy os_policy, bool server);
};
#endif
+
// tcp_segment.cc author davis mcpherson <davmcphe@@cisco.com>
// Created on: Sep 21, 2015
+#include <stream/tcp/tcp_segment_node.h>
#include "flow/flow_control.h"
#include "perf_monitor/perf.h"
#include "protocols/packet.h"
#include "tcp_module.h"
-#include "tcp_segment.h"
THREAD_LOCAL Memcap* tcp_memcap = nullptr;
-TcpSegment::TcpSegment() :
- prev( nullptr ), next( nullptr ), tv( { 0, 0 } ), ts( 0 ), seq( 0 ), orig_dsize( 0 ),
- payload_size( 0 ), urg_offset( 0 ), buffered( false ), data(nullptr), payload( nullptr )
+TcpSegmentNode::TcpSegmentNode() :
+ prev(nullptr), next(nullptr), tv({ 0, 0 }), ts(0), seq(0), orig_dsize(0),
+ payload_size(0), urg_offset(0), buffered(false), data(nullptr), payload(nullptr)
{
-
}
-TcpSegment::~TcpSegment()
+TcpSegmentNode::~TcpSegmentNode()
{
// TODO Auto-generated destructor stub
}
// TcpSegment stuff
//-------------------------------------------------------------------------
-TcpSegment* TcpSegment::init( const struct timeval& tv, const uint8_t* data, unsigned dsize)
+TcpSegmentNode* TcpSegmentNode::init(const struct timeval& tv, const uint8_t* data, unsigned dsize)
{
- TcpSegment* ss;
+ TcpSegmentNode* ss;
- tcp_memcap->alloc( dsize );
- ss = new TcpSegment;
- if( !ss )
+ tcp_memcap->alloc(dsize);
+ ss = new TcpSegmentNode;
+ if ( !ss )
{
- tcp_memcap->dealloc( dsize );
+ tcp_memcap->dealloc(dsize);
return nullptr;
}
- ss->data = ( uint8_t * ) malloc( dsize );
+ ss->data = ( uint8_t* )malloc(dsize);
ss->payload = ss->data;
ss->tv = tv;
memcpy(ss->payload, data, dsize);
return ss;
}
-void TcpSegment::term( void )
+void TcpSegmentNode::term(void)
{
- tcp_memcap->dealloc( orig_dsize );
- free( data );
+ tcp_memcap->dealloc(orig_dsize);
+ free(data);
tcpStats.segs_released++;
delete this;
}
-bool TcpSegment::is_retransmit( const uint8_t* rdata, uint16_t rsize, uint32_t rseq )
+bool TcpSegmentNode::is_retransmit(const uint8_t* rdata, uint16_t rsize, uint32_t rseq)
{
// retransmit must have same payload at same place
- if( !SEQ_EQ( seq, rseq ) )
+ if ( !SEQ_EQ(seq, rseq) )
return false;
- if( ( ( payload_size <= rsize ) and !memcmp( data, rdata, payload_size ) )
- or ( ( payload_size > rsize ) and !memcmp( data, rdata, rsize ) ) )
+ if ( ( ( payload_size <= rsize )and !memcmp(data, rdata, payload_size) )
+ or ( ( payload_size > rsize )and !memcmp(data, rdata, rsize) ) )
return true;
return false;
}
+
#ifndef TCP_SEGMENT_H
#define TCP_SEGMENT_H
+#include "main/snort_debug.h"
#include "protocols/packet.h"
#include "flow/memcap.h"
// ... however, use of padding below is critical, adjust if needed
//-----------------------------------------------------------------
-
-class TcpSegment
+class TcpSegmentNode
{
public:
- TcpSegment();
- virtual ~TcpSegment();
+ TcpSegmentNode();
+ virtual ~TcpSegmentNode();
- static TcpSegment* init( const struct timeval&, const uint8_t*, unsigned );
- static bool needs_pruning( void )
+ static TcpSegmentNode* init(const struct timeval&, const uint8_t*, unsigned);
+ static bool needs_pruning(void)
{
return tcp_memcap->at_max();
}
- void term( void );
- bool is_retransmit( const uint8_t*, uint16_t size, uint32_t );
+ void term(void);
+ bool is_retransmit(const uint8_t*, uint16_t size, uint32_t);
- TcpSegment *prev;
- TcpSegment *next;
+ TcpSegmentNode* prev;
+ TcpSegmentNode* next;
struct timeval tv;
uint32_t ts;
uint8_t* data;
uint8_t* payload;
-
};
class TcpSegmentList
{
public:
- TcpSegment *head;
- TcpSegment *tail;
+ TcpSegmentList(void) :
+ head(nullptr), tail(nullptr), next(nullptr), count(0)
+ {
+ }
+
+ ~TcpSegmentList(void)
+ {
+ clear( );
+ }
+
+ TcpSegmentNode* head;
+ TcpSegmentNode* tail;
// FIXIT-P seglist_base_seq is the sequence number to flush from
// and is valid even when seglist is empty. next points to
// the segment to flush from and is set per packet. should keep
// up to date.
- TcpSegment* next;
+ TcpSegmentNode* next;
+
+ uint32_t count;
- uint32_t clear( void )
+ uint32_t clear(void)
{
- TcpSegment *dump_me;
+ TcpSegmentNode* dump_me;
int i = 0;
- DebugMessage(DEBUG_STREAM_STATE, "Clearing ssment list.\n");
+ DebugMessage(DEBUG_STREAM_STATE, "Clearing segment list.\n");
while ( head )
{
i++;
}
head = tail = next = nullptr;
+ count = 0;
DebugFormat(DEBUG_STREAM_STATE, "Dropped %d segments\n", i);
return i;
}
- void insert( TcpSegment *prev, TcpSegment *ss )
+ void insert(TcpSegmentNode* prev, TcpSegmentNode* ss)
{
- if( prev )
+ if ( prev )
{
ss->next = prev->next;
ss->prev = prev;
prev->next = ss;
- if( ss->next )
+ if ( ss->next )
ss->next->prev = ss;
else
tail = ss;
else
{
ss->next = head;
- if( ss->next )
+ if ( ss->next )
ss->next->prev = ss;
else
tail = ss;
head = ss;
}
+
+ count++;
}
- void remove( TcpSegment *ss )
+ void remove(TcpSegmentNode* ss)
{
if (ss->prev)
ss->prev->next = ss->next;
else
- head = ss->next;
+ head = ss->next;
if (ss->next)
ss->next->prev = ss->prev;
else
tail = ss->prev;
+
+ count--;
}
};
#endif
+
* - limit on number of overlapping packets (done, SAS)
*/
-#include "tcp_session.h"
-
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <errno.h>
#include <assert.h>
-#include "stream_tcp.h"
-#include "tcp_module.h"
-
-// TBD-EDM - these includes are for functions moved to a new file to group related functionality
-// in specific files ... these functional groups will be further refactored as the stream tcp
-// rewrite continues...
-#include "tcp_events.h"
-#include "tcp_debug_trace.h"
-
-#include "stream/libtcp/tcp_state_handler.h"
-#include "tcp_closed_state.h"
-#include "tcp_listen_state.h"
-#include "tcp_syn_sent_state.h"
-#include "tcp_syn_recv_state.h"
-#include "tcp_normalizers.h"
-#include "tcp_reassemblers.h"
-// TBD-EDM
-
#include "main/snort_types.h"
#include "main/snort_debug.h"
#include "main/snort_config.h"
#include "sfip/sf_ip.h"
#include "filters/sfrf.h"
-using namespace tcp;
-
-/* M A C R O S **************************************************/
-
-#define STREAM_UNALIGNED 0
-#define STREAM_ALIGNED 1
-
-#define STREAM_DEFAULT_MAX_QUEUED_BYTES 1048576 /* 1 MB */
-#define AVG_PKT_SIZE 400
-#define STREAM_DEFAULT_MAX_QUEUED_SEGS (STREAM_DEFAULT_MAX_QUEUED_BYTES/AVG_PKT_SIZE)
-
-#define STREAM_DEFAULT_MAX_SMALL_SEG_SIZE 0 /* disabled */
-#define STREAM_DEFAULT_CONSEC_SMALL_SEGS 0 /* disabled */
-
-#define SLAM_MAX 4
-
-/* P R O T O T Y P E S ********************************************/
-
-static int ProcessTcp(Flow*, TcpDataBlock*, StreamTcpConfig*);
+#include "stream/paf.h"
+#include "stream_tcp.h"
+#include "tcp_module.h"
+#include "tcp_event_logger.h"
+#include "tcp_debug_trace.h"
-/* G L O B A L S **************************************************/
+#include "tcp_state_none.h"
+#include "tcp_state_closed.h"
+#include "tcp_state_listen.h"
+#include "tcp_state_syn_sent.h"
+#include "tcp_state_syn_recv.h"
+#include "tcp_state_established.h"
+#include "tcp_state_close_wait.h"
+#include "tcp_state_closing.h"
+#include "tcp_state_fin_wait1.h"
+#include "tcp_state_fin_wait2.h"
+#include "tcp_state_last_ack.h"
+#include "tcp_state_time_wait.h"
-static const char* const reassembly_policy_names[] = { "no policy", "first",
- "last", "linux", "old_linux", "bsd", "macos", "solaris", "irix",
- "hpux11", "hpux10", "windows", "win_2003", "vista", "proxy" };
+#include "tcp_normalizers.h"
+#include "tcp_reassemblers.h"
+#include "tcp_session.h"
#ifdef DEBUG
-static const char* const state_names[] =
-{
- "none",
- "listen",
- "syn_rcvd",
- "syn_sent",
- "established",
- "close_wait",
- "last_ack",
- "fin_wait_1",
- "closing",
- "fin_wait_2",
- "time_wait",
- "closed"
-};
-
const char* const flush_policy_names[] =
{
"ignore",
};
#endif
-//-------------------------------------------------------------------------
-// flush policy stuff
-//-------------------------------------------------------------------------
-
-static inline void init_flush_policy(Flow*, TcpTracker* trk)
-{
- if (!trk->splitter)
- trk->flush_policy = STREAM_FLPOLICY_IGNORE;
- else if (!trk->normalizer->is_tcp_ips_enabled() )
- trk->flush_policy = STREAM_FLPOLICY_ON_ACK;
- else
- trk->flush_policy = STREAM_FLPOLICY_ON_DATA;
-}
-
-void StreamUpdatePerfBaseState(SFBASE *sf_base, Flow *flow, char newState)
+void TcpSession::update_perf_base_state(SFBASE* sf_base, char newState)
{
- if (!flow)
- return;
-
uint32_t session_flags = flow->get_session_flags();
- switch (newState)
+ switch ( newState )
{
- case TCP_STATE_SYN_SENT:
- if (!(session_flags & SSNFLAG_COUNTED_INITIALIZE))
- {
- sf_base->iSessionsInitializing++;
- session_flags |= SSNFLAG_COUNTED_INITIALIZE;
- }
- break;
-
- case TCP_STATE_ESTABLISHED:
- if (!(session_flags & SSNFLAG_COUNTED_ESTABLISH))
- {
- sf_base->iSessionsEstablished++;
+ case TcpStreamTracker::TCP_SYN_SENT:
+ if ( !( session_flags & SSNFLAG_COUNTED_INITIALIZE ) )
+ {
+ sf_base->iSessionsInitializing++;
+ session_flags |= SSNFLAG_COUNTED_INITIALIZE;
+ }
+ break;
- if (perfmon_config && (perfmon_config->perf_flags & SFPERF_FLOWIP))
- UpdateFlowIPState(&sfFlow, &flow->client_ip, &flow->server_ip, SFS_STATE_TCP_ESTABLISHED);
+ case TcpStreamTracker::TCP_ESTABLISHED:
+ if ( !( session_flags & SSNFLAG_COUNTED_ESTABLISH ) )
+ {
+ sf_base->iSessionsEstablished++;
- session_flags |= SSNFLAG_COUNTED_ESTABLISH;
+ if ( perfmon_config && ( perfmon_config->perf_flags & SFPERF_FLOWIP ) )
+ UpdateFlowIPState(&sfFlow, &flow->client_ip,
+ &flow->server_ip, SFS_STATE_TCP_ESTABLISHED);
- if ((session_flags & SSNFLAG_COUNTED_INITIALIZE)
- && !(session_flags & SSNFLAG_COUNTED_CLOSING))
- {
- assert(sf_base->iSessionsInitializing);
- sf_base->iSessionsInitializing--;
- }
- }
- break;
+ session_flags |= SSNFLAG_COUNTED_ESTABLISH;
- case TCP_STATE_CLOSING:
- if (!(session_flags & SSNFLAG_COUNTED_CLOSING))
+ if ( ( session_flags & SSNFLAG_COUNTED_INITIALIZE )
+ && !( session_flags & SSNFLAG_COUNTED_CLOSING ) )
{
- sf_base->iSessionsClosing++;
- session_flags |= SSNFLAG_COUNTED_CLOSING;
-
- if (session_flags & SSNFLAG_COUNTED_ESTABLISH)
- {
- assert(sf_base->iSessionsEstablished);
- sf_base->iSessionsEstablished--;
-
- if (perfmon_config && (perfmon_config->perf_flags & SFPERF_FLOWIP))
- UpdateFlowIPState(&sfFlow, &flow->client_ip, &flow->server_ip, SFS_STATE_TCP_CLOSED);
- }
- else if (session_flags & SSNFLAG_COUNTED_INITIALIZE)
- {
- assert(sf_base->iSessionsInitializing);
- sf_base->iSessionsInitializing--;
- }
+ assert(sf_base->iSessionsInitializing);
+ sf_base->iSessionsInitializing--;
}
- break;
+ }
+ break;
- case TCP_STATE_CLOSED:
- if ( session_flags & SSNFLAG_COUNTED_CLOSING )
- {
- assert(sf_base->iSessionsClosing);
- sf_base->iSessionsClosing--;
- }
- else if (session_flags & SSNFLAG_COUNTED_ESTABLISH)
+ case TcpStreamTracker::TCP_CLOSING:
+ if ( !( session_flags & SSNFLAG_COUNTED_CLOSING ) )
+ {
+ sf_base->iSessionsClosing++;
+ session_flags |= SSNFLAG_COUNTED_CLOSING;
+
+ if ( session_flags & SSNFLAG_COUNTED_ESTABLISH )
{
assert(sf_base->iSessionsEstablished);
sf_base->iSessionsEstablished--;
- if (perfmon_config && (perfmon_config->perf_flags & SFPERF_FLOWIP))
- UpdateFlowIPState(&sfFlow, &flow->client_ip, &flow->server_ip, SFS_STATE_TCP_CLOSED);
+ if ( perfmon_config && ( perfmon_config->perf_flags & SFPERF_FLOWIP ) )
+ UpdateFlowIPState(&sfFlow, &flow->client_ip,
+ &flow->server_ip, SFS_STATE_TCP_CLOSED);
}
- else if (session_flags & SSNFLAG_COUNTED_INITIALIZE)
+ else if ( session_flags & SSNFLAG_COUNTED_INITIALIZE )
{
assert(sf_base->iSessionsInitializing);
sf_base->iSessionsInitializing--;
}
- break;
-
- default:
- break;
- }
-
- flow->update_session_flags( session_flags );
- sf_base->stream_mem_in_use = tcp_memcap->used();
-}
-
-//-------------------------------------------------------------------------
-// config methods
-//-------------------------------------------------------------------------
-
-StreamTcpConfig::StreamTcpConfig()
-{
- policy = StreamPolicy::OS_DEFAULT;
- reassembly_policy = ReassemblyPolicy::OS_DEFAULT;
-
- flags = 0;
- flush_factor = 0;
-
- session_timeout = STREAM_DEFAULT_SSN_TIMEOUT;
- max_window = 0;
- overlap_limit = 0;
-
- max_queued_bytes = STREAM_DEFAULT_MAX_QUEUED_BYTES;
- max_queued_segs = STREAM_DEFAULT_MAX_QUEUED_SEGS;
-
- max_consec_small_segs = STREAM_DEFAULT_CONSEC_SMALL_SEGS;
- max_consec_small_seg_size = STREAM_DEFAULT_MAX_SMALL_SEG_SIZE;
+ }
+ break;
- hs_timeout = -1;
- footprint = 0;
- paf_max = 16384;
-}
+ case TcpStreamTracker::TCP_CLOSED:
+ if ( session_flags & SSNFLAG_COUNTED_CLOSING )
+ {
+ assert(sf_base->iSessionsClosing);
+ sf_base->iSessionsClosing--;
+ }
+ else if ( session_flags & SSNFLAG_COUNTED_ESTABLISH )
+ {
+ assert(sf_base->iSessionsEstablished);
+ sf_base->iSessionsEstablished--;
-inline bool StreamTcpConfig::require_3whs()
-{
- return hs_timeout >= 0;
-}
+ if ( perfmon_config && ( perfmon_config->perf_flags & SFPERF_FLOWIP ) )
+ UpdateFlowIPState(&sfFlow, &flow->client_ip,
+ &flow->server_ip, SFS_STATE_TCP_CLOSED);
+ }
+ else if ( session_flags & SSNFLAG_COUNTED_INITIALIZE )
+ {
+ assert(sf_base->iSessionsInitializing);
+ sf_base->iSessionsInitializing--;
+ }
+ break;
-inline bool StreamTcpConfig::midstream_allowed(Packet* p)
-{
- if ((hs_timeout < 0) || (p->pkth->ts.tv_sec - packet_first_time() < hs_timeout))
- return true;
+ default:
+ break;
+ }
- return false;
+ flow->update_session_flags(session_flags);
+ sf_base->stream_mem_in_use = tcp_memcap->used();
}
//-------------------------------------------------------------------------
// make sense of the code in this file.
//-------------------------------------------------------------------------
-static void StreamPrintTcpConfig(StreamTcpConfig* config)
-{
- LogMessage("Stream TCP Policy config:\n");
- LogMessage(" Reassembly Policy: %s\n",
- reassembly_policy_names[ static_cast<int>( config->reassembly_policy ) ] );
- LogMessage(" Timeout: %d seconds\n", config->session_timeout);
-
- if (config->max_window != 0)
- LogMessage(" Max TCP Window: %u\n", config->max_window);
-
- if (config->overlap_limit)
- LogMessage(" Limit on TCP Overlaps: %d\n", config->overlap_limit);
-
- if (config->max_queued_bytes != 0)
- LogMessage(" Maximum number of bytes to queue per session: %d\n", config->max_queued_bytes);
-
- if (config->max_queued_segs != 0)
- LogMessage(" Maximum number of segs to queue per session: %d\n", config->max_queued_segs);
-
- if (config->flags)
- {
- LogMessage(" Options:\n");
- if (config->flags & STREAM_CONFIG_IGNORE_ANY)
- LogMessage(" Ignore Any -> Any Rules: YES\n");
-
- if (config->flags & STREAM_CONFIG_NO_ASYNC_REASSEMBLY)
- LogMessage( " Don't queue packets on one-sided sessions: YES\n");
- }
-
- if (config->hs_timeout < 0)
- LogMessage(" Require 3-Way Handshake: NO\n");
- else
- LogMessage(" Require 3-Way Handshake: after %d seconds\n", config->hs_timeout);
-
-#ifdef REG_TEST
- LogMessage(" TCP Session Size: %lu\n",sizeof(TcpSession));
-#endif
-}
-
-//-------------------------------------------------------------------------
-// attribute table foo
-//-------------------------------------------------------------------------
-
-int StreamVerifyTcpConfig(SnortConfig*, StreamTcpConfig*)
-{
- return 0;
-}
-
#ifdef DEBUG_STREAM_EX
-static void PrintStateMgr(StateMgr* s)
-{
- LogMessage("StateMgr:\n");
- LogMessage(" state: %s\n", state_names[s->state]);
- LogMessage(" state_queue: %s\n", state_names[s->state_queue]);
- LogMessage(" expected_flags: 0x%X\n", s->expected_flags);
- LogMessage(" transition_seq: 0x%X\n", s->transition_seq);
- LogMessage(" stq_get_seq: %d\n", s->stq_get_seq);
-}
-
-static void PrintTcpTracker(TcpTracker *s)
-{
- LogMessage(" + TcpTracker +\n");
- LogMessage(" isn: 0x%X\n", s->isn);
- LogMessage(" ts_last: %u\n", s->ts_last);
- LogMessage(" wscale: %u\n", s->wscale);
- LogMessage(" mss: 0x%08X\n", s->mss);
- LogMessage(" l_unackd: %X\n", s->l_unackd);
- LogMessage(" l_nxt_seq: %X\n", s->l_nxt_seq);
- LogMessage(" l_window: %u\n", s->l_window);
- LogMessage(" r_nxt_ack: %X\n", s->r_nxt_ack);
- LogMessage(" r_win_base: %X\n", s->r_win_base);
- LogMessage(" seglist_base_seq: %X\n", s->reassembler->get_seglist_base_seq( ));
- LogMessage(" seglist: %p\n", (void*)s->seglist);
- LogMessage(" seglist_tail: %p\n", (void*)s->seglist_tail);
- LogMessage(" seg_count: %d\n", s->reassembler->get_seg_count());
- LogMessage(" seg_bytes_total: %d\n", s->reassembler->get_seg_bytes_total());
- LogMessage(" seg_bytes_logical: %d\n", s->get_seg_bytes_logical() );
-
- PrintStateMgr(&s->s_mgr);
-}
-
-static void PrintTcpSession(TcpSession* ts)
-{
- char buf[64];
-
- LogMessage("TcpSession:\n");
- sfip_ntop(&ts->flow->server_ip, buf, sizeof(buf));
- LogMessage(" server IP: %s\n", buf);
- sfip_ntop(&ts->flow->client_ip, buf, sizeof(buf));
- LogMessage(" client IP: %s\n", buf);
-
- LogMessage(" server port: %d\n", ts->flow->server_port);
- LogMessage(" client port: %d\n", ts->flow->client_port);
-
- LogMessage(" flags: 0x%X\n", ts->flow->get_session_flags());
-
- LogMessage("Client Tracker:\n");
- PrintTcpTracker(&ts->client);
- LogMessage("Server Tracker:\n");
- PrintTcpTracker(&ts->server);
-}
-
-static void PrintTcpDataBlock(TcpDataBlock* tdb)
-{
- LogMessage("TcpDataBlock:\n");
- LogMessage(" seq: 0x%08X\n", tdb->seq);
- LogMessage(" ack: 0x%08X\n", tdb->ack);
- LogMessage(" win: %d\n", tdb->win);
- LogMessage(" end: 0x%08X\n", tdb->end_seq);
-}
-
+// FIXIT - FlushMgr is no longer defined - confirm this and delete or refactor to use
+// what replaced FlushMgr
static void PrintFlushMgr(FlushMgr* fm)
{
if (fm == NULL)
switch (fm->flush_policy)
{
- case STREAM_FLPOLICY_IGNORE:
- DebugMessage( DEBUG_STREAM_STATE, " IGNORE\n");
- break;
+ case STREAM_FLPOLICY_IGNORE:
+ DebugMessage(DEBUG_STREAM_STATE, " IGNORE\n");
+ break;
- case STREAM_FLPOLICY_ON_ACK:
- DebugMessage( DEBUG_STREAM_STATE, " PROTOCOL\n");
- break;
+ case STREAM_FLPOLICY_ON_ACK:
+ DebugMessage(DEBUG_STREAM_STATE, " PROTOCOL\n");
+ break;
- case STREAM_FLPOLICY_ON_DATA:
- DebugMessage( DEBUG_STREAM_STATE, " PROTOCOL_IPS\n");
- break;
+ case STREAM_FLPOLICY_ON_DATA:
+ DebugMessage(DEBUG_STREAM_STATE, " PROTOCOL_IPS\n");
+ break;
}
}
#endif // DEBUG_STREAM_EX
+static inline int is_mac_address_valid(TcpTracker* talker, TcpTracker* listener, Packet* p)
+{
+ int event_code = 0;
+ bool t_hijack = true, l_hijack = true;
-//-------------------------------------------------------------------------
-// ssn ingress is client; ssn egress is server
+ if (!(p->proto_bits & PROTO_BIT__ETH))
+ return 0;
-//-------------------------------------------------------------------------
+ // if flag is set, gauranteed to have an eth layer
+ const eth::EtherHdr* eh = layer::get_eth_layer(p);
-static inline int IsBetween(uint32_t low, uint32_t high, uint32_t cur)
-{
- DebugFormat(DEBUG_STREAM_STATE, "(%X, %X, %X) = (low, high, cur)\n", low,high,cur);
+ if ( talker->compare_mac_addresses(eh->ether_src) )
+ {
+ t_hijack = false;
+ if ( listener->compare_mac_addresses(eh->ether_dst) )
+ l_hijack = false;
+ }
+ else if ( listener->compare_mac_addresses(eh->ether_dst) )
+ l_hijack = false;
- /* If we haven't seen anything, ie, low & high are 0, return true */
- if ((low == 0) && (low == high))
- return 1;
+ if ( t_hijack & l_hijack )
+ {
+ if ( talker->compare_mac_addresses(eh->ether_dst) &&
+ listener->compare_mac_addresses(eh->ether_src) )
+ // this is probably a tap
+ return event_code;
+ }
- return (SEQ_GEQ(cur, low) && SEQ_LEQ(cur, high));
-}
+ if ( t_hijack )
+ {
+ if ( p->packet_flags & PKT_FROM_CLIENT )
+ event_code |= EVENT_SESSION_HIJACK_CLIENT;
+ else
+ event_code |= EVENT_SESSION_HIJACK_SERVER;
+ }
+ if ( l_hijack )
+ {
+ if ( p->packet_flags & PKT_FROM_CLIENT )
+ event_code |= EVENT_SESSION_HIJACK_SERVER;
+ else
+ event_code |= EVENT_SESSION_HIJACK_CLIENT;
+ }
-// ack number must ack syn
-static inline int ValidRstSynSent(TcpTracker *st, TcpDataBlock *tdb)
-{
- return tdb->ack == st->l_unackd;
+ return event_code;
}
-
#ifdef S5_PEDANTIC
// From RFC 793:
//
// >0 >0 RCV.NXT =< SEG.SEQ < RCV.NXT+RCV.WND
// or RCV.NXT =< SEG.SEQ+SEG.LEN-1 < RCV.NXT+RCV.WND
//
-static inline int ValidSeq( const Packet* p, Flow* flow, TcpTracker *st, TcpDataBlock *tdb )
+static inline int ValidSeq(const Packet* p, Flow* flow, TcpTracker* st, TcpSegmentDescriptor& tsd)
{
- uint32_t win = st->normalizer->get_stream_window(flow, st, tdb);
+ uint32_t win = st->normalizer->get_stream_window(flow, st, tsd);
if ( !p->dsize )
{
if ( !win )
{
- return ( tdb->seq == st->r_win_base );
+ return ( tsd.get_seq() == st->r_win_base );
}
- return SEQ_LEQ(st->r_win_base, tdb->seq) &&
- SEQ_LT(tdb->seq, st->r_win_base+win);
+ return SEQ_LEQ(st->r_win_base, tsd.get_seq()) &&
+ SEQ_LT(tsd.get_seq(), st->r_win_base+win);
}
if ( !win )
return 0;
- if ( SEQ_LEQ(st->r_win_base, tdb->seq) &&
- SEQ_LT(tdb->seq, st->r_win_base+win) )
+ if ( SEQ_LEQ(st->r_win_base, tsd.get_seq()) &&
+ SEQ_LT(tsd.get_seq(), st->r_win_base+win) )
return 1;
- return SEQ_LEQ(st->r_win_base, tdb->end_seq) &&
- SEQ_LT(tdb->end_seq, st->r_win_base+win);
+ return SEQ_LEQ(st->r_win_base, tsd.get_end_seq()) &&
+ SEQ_LT(tsd.get_end_seq(), st->r_win_base+win);
}
#else
-static inline int ValidSeq( TcpTracker *st, TcpDataBlock *tdb)
+static inline int ValidSeq(TcpTracker* st, TcpSegmentDescriptor& tsd)
{
int right_ok;
uint32_t left_seq;
- DebugFormat(DEBUG_STREAM_STATE, "Checking end_seq (%X) > r_win_base (%X) && seq (%X) < r_nxt_ack(%X)\n",
- tdb->end_seq, st->r_win_base, tdb->seq, st->r_nxt_ack + st->normalizer->get_stream_window( tdb ));
+ DebugFormat(DEBUG_STREAM_STATE,
+ "Checking end_seq (%X) > r_win_base (%X) && seq (%X) < r_nxt_ack(%X)\n",
+ tsd.get_end_seq(), st->r_win_base, tsd.get_seq(), st->r_nxt_ack +
+ st->normalizer->get_stream_window(tsd));
- if (SEQ_LT(st->r_nxt_ack, st->r_win_base))
+ if ( SEQ_LT(st->r_nxt_ack, st->r_win_base) )
left_seq = st->r_nxt_ack;
else
left_seq = st->r_win_base;
- if (tdb->pkt->dsize)
- right_ok = SEQ_GT(tdb->end_seq, left_seq);
+ if ( tsd.get_pkt()->dsize )
+ right_ok = SEQ_GT(tsd.get_end_seq(), left_seq);
else
- right_ok = SEQ_GEQ(tdb->end_seq, left_seq);
+ right_ok = SEQ_GEQ(tsd.get_end_seq(), left_seq);
- if (right_ok)
+ if ( right_ok )
{
- uint32_t win = st->normalizer->get_stream_window( tdb );
+ uint32_t win = st->normalizer->get_stream_window(tsd);
- if (SEQ_LEQ(tdb->seq, st->r_win_base + win))
+ if ( SEQ_LEQ(tsd.get_seq(), st->r_win_base + win) )
{
DebugMessage(DEBUG_STREAM_STATE, "seq is within window!\n");
return 1;
- } else
+ }
+ else
{
DebugMessage(DEBUG_STREAM_STATE, "seq is past the end of the window!\n");
}
#endif
-static inline void UpdateSsn( TcpTracker *rcv, TcpTracker *snd, TcpDataBlock *tdb)
+static inline void UpdateSsn(TcpTracker* rcv, TcpTracker* snd, TcpSegmentDescriptor& tsd)
{
#if 0
- if (
- // FIXIT-L these checks are a hack to avoid off by one normalization
- // due to FIN ... if last segment filled a hole, r_nxt_ack is not at
- // end of data, FIN is ignored so sequence isn't bumped, and this
- // forces seq-- on ACK of FIN. :(
- rcv->s_mgr.state == TCP_STATE_ESTABLISHED &&
- rcv->s_mgr.state_queue == TCP_STATE_NONE &&
- Normalize_IsEnabled(NORM_TCP_IPS) )
- {
- // walk the seglist until a gap or tdb->ack whichever is first
- // if a gap exists prior to ack, move ack back to start of gap
- TcpSegment* seg = snd->seglist;
-
- // FIXIT-L must check ack oob with empty seglist
- // FIXIT-L add lower gap bound to tracker for efficiency?
- while ( seg )
- {
+ // FIXIT-L these checks are a hack to avoid off by one normalization
+ // due to FIN ... if last segment filled a hole, r_nxt_ack is not at
+ // end of data, FIN is ignored so sequence isn't bumped, and this
+ // forces seq-- on ACK of FIN. :(
+ if ( rcv->get_tcp_state() == TcpStreamTracker::TCP_ESTABLISHED &&
+ rcv->s_mgr.state_queue == TcpStreamTracker::TCP_STATE_NONE &&
+ Normalize_IsEnabled(NORM_TCP_IPS) )
+ {
+ // walk the seglist until a gap or tsd.ack whichever is first
+ // if a gap exists prior to ack, move ack back to start of gap
+ TcpSegment* seg = snd->seglist;
+
+ // FIXIT-L must check ack oob with empty seglist
+ // FIXIT-L add lower gap bound to tracker for efficiency?
+ while ( seg )
+ {
uint32_t seq = seg->seq + seg->size;
- if ( SEQ_LEQ(tdb->ack, seq) )
- break;
+ if ( SEQ_LEQ(tsd.get_ack(), seq) )
+ break;
seg = seg->next;
if ( !seg || seg->seq > seq )
{
// normalize here
- tdb->ack = seq;
+ tsd.set_ack(seq);
tcph->th_ack = htonl(seq);
p->packet_flags |= PKT_MODIFIED;
break;
}
- }
- }
+ }
+ }
#endif
// ** if we don't see a segment, we can't track seq at ** below
// so we update the seq by the ack if it is beyond next expected
- if (SEQ_GT(tdb->ack, rcv->l_unackd))
- rcv->l_unackd = tdb->ack;
+ if ( SEQ_GT(tsd.get_ack(), rcv->get_snd_una() ) )
+ rcv->set_snd_una(tsd.get_ack() );
// ** this is how we track the last seq number sent
// as is l_unackd is the "last left" seq recvd
- snd->l_unackd = tdb->seq;
+ snd->set_snd_una(tsd.get_seq() );
- if (SEQ_GT(tdb->end_seq, snd->l_nxt_seq))
- snd->l_nxt_seq = tdb->end_seq;
+ if ( SEQ_GT(tsd.get_end_seq(), snd->get_snd_nxt() ) )
+ snd->set_snd_nxt(tsd.get_end_seq() );
- if (!SEQ_EQ(snd->r_win_base, tdb->ack))
+ if ( !SEQ_EQ(snd->r_win_base, tsd.get_ack() ) )
{
snd->small_seg_count = 0;
}
#ifdef S5_PEDANTIC
- if ( SEQ_GT(tdb->ack, snd->r_win_base) &&
- SEQ_LEQ(tdb->ack, snd->r_nxt_ack) )
+ if ( SEQ_GT(tsd.get_ack(), snd->r_win_base) &&
+ SEQ_LEQ(tsd.get_ack(), snd->r_nxt_ack) )
#else
- if (SEQ_GT(tdb->ack, snd->r_win_base))
+ if ( SEQ_GT(tsd.get_ack(), snd->r_win_base) )
#endif
- snd->r_win_base = tdb->ack;
-
- snd->l_window = tdb->win;
-}
-
-static inline void SetupTcpDataBlock(TcpDataBlock* tdb, Packet* p)
-{
- tdb->pkt = p;
- tdb->seq = ntohl(p->ptrs.tcph->th_seq);
- tdb->ack = ntohl(p->ptrs.tcph->th_ack);
- tdb->win = ntohs(p->ptrs.tcph->th_win);
- tdb->end_seq = tdb->seq + (uint32_t) p->dsize;
- tdb->ts = 0;
-
- if( p->ptrs.tcph->is_syn() )
- {
- tdb->end_seq++;
- if( !p->ptrs.tcph->is_ack() )
- EventInternal(INTERNAL_EVENT_SYN_RECEIVED);
- }
- // don't bump end_seq for fin here
- // we will bump if/when fin is processed
+ snd->r_win_base = tsd.get_ack();
-#ifdef DEBUG_STREAM_EX
- PrintTcpDataBlock(&tdb);
-#endif
+ snd->set_snd_wnd(tsd.get_win() );
}
-
-static void TcpSessionClear(Flow* flow, TcpSession* tcpssn, int freeApplicationData)
+void TcpSession::clear_session(int freeApplicationData)
{
// update stats
- if (tcpssn->tcp_init)
+ if ( tcp_init )
tcpStats.trackers_released++;
- else if (tcpssn->lws_init)
+ else if ( lws_init )
tcpStats.no_pickups++;
else
return;
- StreamUpdatePerfBaseState(&sfBase, tcpssn->flow, TCP_STATE_CLOSED);
+ update_perf_base_state(&sfBase, TcpStreamTracker::TCP_CLOSED);
RemoveStreamSession(&sfBase);
- if (flow->get_session_flags() & SSNFLAG_PRUNED)
+ if ( flow->get_session_flags() & SSNFLAG_PRUNED )
CloseStreamSession(&sfBase, SESSION_CLOSED_PRUNED);
- else if (flow->get_session_flags() & SSNFLAG_TIMEDOUT)
+ else if ( flow->get_session_flags() & SSNFLAG_TIMEDOUT )
CloseStreamSession(&sfBase, SESSION_CLOSED_TIMEDOUT);
else
CloseStreamSession(&sfBase, SESSION_CLOSED_NORMALLY);
- tcpssn->set_splitter(true, nullptr);
- tcpssn->set_splitter(false, nullptr);
+ set_splitter(true, nullptr);
+ set_splitter(false, nullptr);
DebugFormat(DEBUG_STREAM_STATE, "In TcpSessionClear, %lu bytes in use\n", tcp_memcap->used());
- if( tcpssn->client.reassembler )
+ if ( client->reassembler )
{
- DebugFormat(DEBUG_STREAM_STATE, "client has %d segs queued, freeing all.\n", tcpssn->client.reassembler->get_seg_count());
- tcpssn->client.reassembler->purge_segment_list( );
+ DebugFormat(DEBUG_STREAM_STATE, "client has %d segs queued, freeing all.\n",
+ client->reassembler->get_seg_count());
+ client->reassembler->purge_segment_list();
}
- if( tcpssn->server.reassembler )
+ if ( server->reassembler )
{
- DebugFormat(DEBUG_STREAM_STATE, "server has %d segs queued, freeing all\n", tcpssn->server.reassembler->get_seg_count());
- tcpssn->server.reassembler->purge_segment_list( );
+ DebugFormat(DEBUG_STREAM_STATE, "server has %d segs queued, freeing all\n",
+ server->reassembler->get_seg_count());
+ server->reassembler->purge_segment_list();
}
- paf_clear(&tcpssn->client.paf_state);
- paf_clear(&tcpssn->server.paf_state);
+ paf_clear(&client->paf_state);
+ paf_clear(&server->paf_state);
// update light-weight state
- if (freeApplicationData == 2)
+ if ( freeApplicationData == 2 )
flow->restart(true);
else
flow->clear(freeApplicationData);
// generate event for rate filtering
- EventInternal(INTERNAL_EVENT_SESSION_DEL);
+ tel->EventInternal(INTERNAL_EVENT_SESSION_DEL);
DebugFormat(DEBUG_STREAM_STATE, "After cleaning, %lu bytes in use\n", tcp_memcap->used());
- tcpssn->lws_init = tcpssn->tcp_init = false;
-}
-
-
-static void TcpSessionCleanup(Flow* flow, int freeApplicationData, Packet* p =
- nullptr)
-{
- TcpSession* tcpssn = (TcpSession*) flow->session;
-
- if( tcpssn->tcp_init )
- {
- // FIXIT - this function does both client & server sides...refactor to do one and
- // call for each
- tcpssn->client.reassembler->flush_queued_segments(flow, true, p);
- tcpssn->server.reassembler->flush_queued_segments(flow, true, p);
- TcpSessionClear(flow, tcpssn, freeApplicationData);
- }
-}
-
-
-static uint32_t StreamGetMss( Packet* p, uint16_t* value )
-{
- DebugMessage(DEBUG_STREAM_STATE, "Getting MSS...\n");
-
- TcpOptIterator iter(p->ptrs.tcph, p);
- for (const TcpOption& opt : iter)
- {
- if (opt.code == TcpOptCode::MAXSEG)
- {
- *value = EXTRACT_16BITS(opt.data);
- DebugFormat(DEBUG_STREAM_STATE, "Found MSS %u\n", *value);
- return TF_MSS;
- }
- }
-
- *value = 0;
-
- DebugMessage(DEBUG_STREAM_STATE, "No MSS...\n");
-
- return TF_NONE;
-}
-
-static uint32_t StreamGetWscale(Packet* p, uint16_t* value)
-{
- DebugMessage(DEBUG_STREAM_STATE, "Getting wscale...\n");
-
- TcpOptIterator iter(p->ptrs.tcph, p);
-
- // using const because non-const is not supported
- for (const TcpOption& opt : iter)
- {
- if (opt.code == TcpOptCode::WSCALE)
- {
- *value = (uint16_t) opt.data[0];
- DebugFormat(DEBUG_STREAM_STATE, "Found wscale %d\n", *value);
-
- /* If scale specified in option is larger than 14,
- * use 14 because of limitation in the math of
- * shifting a 32bit value (max scaled window is 2^30th).
- *
- * See RFC 1323 for details.
- */
- if (*value > 14)
- *value = 14;
-
- return TF_WSCALE;
- }
- }
-
- *value = 0;
- DebugMessage(DEBUG_STREAM_STATE, "No wscale...\n");
-
- return TF_NONE;
+ lws_init = tcp_init = false;
}
-static uint32_t StreamPacketHasWscale( Packet* p )
+void TcpSession::cleanup_session(int freeApplicationData, Packet* p)
{
- uint16_t wscale;
+ // FIXIT - this function does both client & server sides...refactor to do one and
+ // call for each
+ if ( client->reassembler != nullptr )
+ client->reassembler->flush_queued_segments(flow, true, p);
+ if ( server->reassembler != nullptr )
+ server->reassembler->flush_queued_segments(flow, true, p);
- DebugMessage(DEBUG_STREAM_STATE, "Checking for wscale...\n");
-
- return StreamGetWscale(p, &wscale);
+ clear_session(freeApplicationData);
}
#if 0
-static inline int IsWellFormed(Packet *p, TcpTracker *ts)
+static inline int IsWellFormed(Packet* p, TcpTracker* ts)
{
return ( !ts->mss || (p->dsize <= ts->mss) );
}
#endif
-static void FinishServerInit( TcpDataBlock* tdb, TcpSession* ssn )
+void TcpSession::FinishServerInit(TcpSegmentDescriptor& tsd)
{
- TcpTracker* server;
- TcpTracker* client;
- const tcp::TCPHdr* tcph = tdb->pkt->ptrs.tcph;
-
- // FIXIT - can tcp session be null at this point?
- if( !ssn )
- return;
+ const tcp::TCPHdr* tcph = tsd.get_tcph();
- server = &ssn->server;
- client = &ssn->client;
+ server->set_snd_wnd(tsd.get_win() );
+ server->set_snd_una(tsd.get_seq() + 1);
+ server->set_snd_nxt(server->get_snd_una() );
+ server->set_iss(tsd.get_seq() );
- server->l_window = tdb->win;
- server->l_unackd = tdb->seq + 1;
- server->l_nxt_seq = server->l_unackd;
- server->isn = tdb->seq;
+ client->r_nxt_ack = tsd.get_end_seq();
- client->r_nxt_ack = tdb->end_seq;
+ if ( tcph->is_fin() )
+ server->set_snd_nxt(server->get_snd_nxt() - 1);
- if( tcph->is_fin() )
- server->l_nxt_seq--;
-
- if( !( ssn->flow->session_state & STREAM_STATE_MIDSTREAM ) )
+ if ( !( flow->session_state & STREAM_STATE_MIDSTREAM ) )
{
- server->s_mgr.state = TCP_STATE_SYN_RCVD;
- client->reassembler->set_seglist_base_seq( server->l_unackd );
- client->r_win_base = tdb->end_seq;
+ server->set_tcp_state(TcpStreamTracker::TCP_SYN_RECV);
+ client->reassembler->set_seglist_base_seq(server->get_snd_una() );
+ client->r_win_base = tsd.get_end_seq();
}
else
{
- client->reassembler->set_seglist_base_seq( tdb->seq );
- client->r_win_base = tdb->seq;
+ client->reassembler->set_seglist_base_seq(tsd.get_seq() );
+ client->r_win_base = tsd.get_seq();
}
- server->flags |= server->normalizer->get_tcp_timestamp(tdb, false);
- server->ts_last = tdb->ts;
+ server->flags |= server->normalizer->get_tcp_timestamp(tsd, false);
+ server->ts_last = tsd.get_ts();
if (server->ts_last == 0)
server->flags |= TF_TSTAMP_ZERO;
else
- server->ts_last_pkt = tdb->pkt->pkth->ts.tv_sec;
+ server->set_ts_last_packet(tsd.get_pkt()->pkth->ts.tv_sec);
- server->flags |= StreamGetMss(tdb->pkt, &server->mss);
- server->flags |= StreamGetWscale(tdb->pkt, &server->wscale);
+ server->flags |= tsd.init_mss(&server->mss);
+ server->flags |= tsd.init_wscale(&server->wscale);
#ifdef DEBUG_STREAM_EX
PrintTcpSession(ssn);
#endif
}
-static inline void EndOfFileHandle(Packet* p, TcpSession* tcpssn)
+void TcpSession::EndOfFileHandle(Packet* p)
{
- tcpssn->flow->call_handlers(p, true);
+ flow->call_handlers(p, true);
}
-static inline bool flow_exceeds_config_thresholds( TcpTracker *rcv, TcpSession *tcpssn, TcpDataBlock *tdb,
- StreamTcpConfig* config )
+bool TcpSession::flow_exceeds_config_thresholds(TcpTracker* rcv, TcpSegmentDescriptor& tsd)
{
if (rcv->flush_policy == STREAM_FLPOLICY_IGNORE)
{
return true;
}
- if( ( config->flags & STREAM_CONFIG_NO_ASYNC_REASSEMBLY ) && !tcpssn->flow->two_way_traffic() )
+ if ( ( config->flags & STREAM_CONFIG_NO_ASYNC_REASSEMBLY ) && !flow->two_way_traffic() )
return true;
- if( config->max_consec_small_segs && ( tdb->pkt->dsize < config->max_consec_small_seg_size ) )
+ if ( config->max_consec_small_segs && ( tsd.get_pkt()->dsize <
+ config->max_consec_small_seg_size ) )
{
rcv->small_seg_count++;
- if( rcv->small_seg_count > config->max_consec_small_segs )
+ if ( rcv->small_seg_count > config->max_consec_small_segs )
{
/* Above threshold, log it... in this TCP policy,
* action controlled by preprocessor rule. */
- EventMaxSmallSegsExceeded();
+ tel->EventMaxSmallSegsExceeded();
/* Reset counter, so we're not too noisy */
rcv->small_seg_count = 0;
}
}
- if( config->max_queued_bytes
- && ( rcv->reassembler->get_seg_bytes_total() > config->max_queued_bytes ) )
+ if ( config->max_queued_bytes
+ && ( rcv->reassembler->get_seg_bytes_total() > config->max_queued_bytes ) )
{
tcpStats.max_bytes++;
return true;
}
- if( config->max_queued_segs
- && ( rcv->reassembler->get_seg_count() + 1 > config->max_queued_segs ) )
+ if ( config->max_queued_segs
+ && ( rcv->reassembler->get_seg_count() + 1 > config->max_queued_segs ) )
{
tcpStats.max_segs++;
return true;
return false;
}
-static void ProcessTcpStream(TcpTracker *rcv, TcpSession *tcpssn, TcpDataBlock *tdb,
- StreamTcpConfig* config)
+void TcpSession::process_tcp_stream(TcpTracker* rcv, TcpSegmentDescriptor& tsd)
{
- DebugFormat(DEBUG_STREAM_STATE, "In ProcessTcpStream(), %d bytes to queue\n", tdb->pkt->dsize);
+ DebugFormat(DEBUG_STREAM_STATE, "In ProcessTcpStream(), %d bytes to queue\n",
+ tsd.get_pkt()->dsize);
- if (tdb->pkt->packet_flags & PKT_IGNORE)
+ if (tsd.get_pkt()->packet_flags & PKT_IGNORE)
return;
- tcpssn->SetPacketHeaderFoo( tdb->pkt );
+ SetPacketHeaderFoo(tsd.get_pkt() );
- if( flow_exceeds_config_thresholds( rcv, tcpssn, tdb, config ) )
+ if ( flow_exceeds_config_thresholds(rcv, tsd) )
return;
DebugMessage(DEBUG_STREAM_STATE, "queuing segment\n");
- rcv->reassembler->queue_packet_for_reassembly( tdb );
+ rcv->reassembler->queue_packet_for_reassembly(tsd);
// Alert if overlap limit exceeded
- if( ( rcv->config->overlap_limit )
- && ( rcv->reassembler->get_overlap_count() > rcv->config->overlap_limit ) )
+ if ( ( config->overlap_limit )
+ && ( rcv->reassembler->get_overlap_count() > config->overlap_limit ) )
{
- EventExcessiveOverlap();
- rcv->reassembler->set_overlap_count( 0 );
+ tel->EventExcessiveOverlap();
+ rcv->reassembler->set_overlap_count(0);
}
}
-static int ProcessTcpData(TcpTracker *listener, TcpSession *tcpssn,
- TcpDataBlock *tdb, StreamTcpConfig *config)
+int TcpSession::process_tcp_data(TcpTracker* listener, TcpSegmentDescriptor& tsd)
{
Profile profile(s5TcpDataPerfStats);
- const tcp::TCPHdr* tcph = tdb->pkt->ptrs.tcph;
- uint32_t seq = tdb->seq;
+ const tcp::TCPHdr* tcph = tsd.get_tcph();
+ uint32_t seq = tsd.get_seq();
- if( tcph->is_syn() )
+ if ( tcph->is_syn() )
{
if (listener->normalizer->get_os_policy() == StreamPolicy::OS_MACOS)
seq++;
else
{
DebugMessage(DEBUG_STREAM_STATE, "Bailing, data on SYN, not MAC Policy!\n");
- listener->normalizer->trim_syn_payload( tdb );
+ listener->normalizer->trim_syn_payload(tsd);
return STREAM_UNALIGNED;
}
}
if (seq == listener->r_nxt_ack)
{
/* check if we're in the window */
- if (listener->config->policy != StreamPolicy::OS_PROXY
- and listener->normalizer->get_stream_window( tdb ) == 0)
+ if (config->policy != StreamPolicy::OS_PROXY
+ and listener->normalizer->get_stream_window(tsd) == 0)
{
DebugMessage(DEBUG_STREAM_STATE, "Bailing, we're out of the window!\n");
- listener->normalizer->trim_win_payload( tdb );
+ listener->normalizer->trim_win_payload(tsd);
return STREAM_UNALIGNED;
}
/* move the ack boundry up, this is the only way we'll accept data */
// FIXIT-L for ips, must move all the way to first hole or right end
- if (listener->s_mgr.state_queue == TCP_STATE_NONE)
- listener->r_nxt_ack = tdb->end_seq;
+ if ( listener->s_mgr.state_queue == TcpStreamTracker::TCP_STATE_NONE )
+ listener->r_nxt_ack = tsd.get_end_seq();
- if (tdb->pkt->dsize != 0)
+ if (tsd.get_pkt()->dsize != 0)
{
- if (!(tcpssn->flow->get_session_flags() & SSNFLAG_STREAM_ORDER_BAD))
- tdb->pkt->packet_flags |= PKT_STREAM_ORDER_OK;
+ if (!( flow->get_session_flags() & SSNFLAG_STREAM_ORDER_BAD))
+ tsd.get_pkt()->packet_flags |= PKT_STREAM_ORDER_OK;
- ProcessTcpStream(listener, tcpssn, tdb, config);
+ process_tcp_stream(listener, tsd);
/* set flags to session flags */
return STREAM_ALIGNED;
// original data. Let the reassembly policy decide how to handle the overlapping data.
// See HP, Solaris, et al. for those that favor duplicate data over the original in
// some cases.
- DebugFormat(DEBUG_STREAM_STATE, "out of order segment (tdb->seq: 0x%X l->r_nxt_ack: 0x%X!\n",
- tdb->seq, listener->r_nxt_ack);
+ DebugFormat(DEBUG_STREAM_STATE,
+ "out of order segment (tsd.seq: 0x%X l->r_nxt_ack: 0x%X!\n",
+ tsd.get_seq(), listener->r_nxt_ack);
- if (listener->s_mgr.state_queue == TCP_STATE_NONE)
+ if (listener->s_mgr.state_queue == TcpStreamTracker::TCP_STATE_NONE)
{
/* check if we're in the window */
- if (listener->config->policy != StreamPolicy::OS_PROXY
- and listener->normalizer->get_stream_window( tdb ) == 0)
+ if (config->policy != StreamPolicy::OS_PROXY
+ and listener->normalizer->get_stream_window(tsd) == 0)
{
DebugMessage(DEBUG_STREAM_STATE, "Bailing, we're out of the window!\n");
- listener->normalizer->trim_win_payload( tdb );
+ listener->normalizer->trim_win_payload(tsd);
return STREAM_UNALIGNED;
}
- if ((listener->s_mgr.state == TCP_STATE_ESTABLISHED)
- && (listener->flush_policy == STREAM_FLPOLICY_IGNORE))
+ if ((listener->get_tcp_state() == TcpStreamTracker::TCP_ESTABLISHED)
+ && (listener->flush_policy == STREAM_FLPOLICY_IGNORE))
{
- if (SEQ_GT(tdb->end_seq, listener->r_nxt_ack))
+ if (SEQ_GT(tsd.get_end_seq(), listener->r_nxt_ack))
{
// set next ack so we are within the window going forward on this side.
// FIXIT-L for ips, must move all the way to first hole or right end
- listener->r_nxt_ack = tdb->end_seq;
+ listener->r_nxt_ack = tsd.get_end_seq();
}
}
}
- if (tdb->pkt->dsize != 0)
+ if (tsd.get_pkt()->dsize != 0)
{
- if (!(tcpssn->flow->get_session_flags() & SSNFLAG_STREAM_ORDER_BAD))
+ if (!( flow->get_session_flags() & SSNFLAG_STREAM_ORDER_BAD))
{
- if (!SEQ_LEQ((tdb->seq + tdb->pkt->dsize), listener->r_nxt_ack))
- tcpssn->flow->set_session_flags( SSNFLAG_STREAM_ORDER_BAD );
+ if (!SEQ_LEQ((tsd.get_seq() + tsd.get_pkt()->dsize), listener->r_nxt_ack))
+ flow->set_session_flags(SSNFLAG_STREAM_ORDER_BAD);
}
- ProcessTcpStream(listener, tcpssn, tdb, config);
+ process_tcp_stream(listener, tsd);
}
}
return STREAM_UNALIGNED;
}
-static void set_os_policy(Flow* flow, TcpSession* tcpssn)
+void TcpSession::set_os_policy(void)
{
StreamPolicy client_os_policy = flow->ssn_policy ?
- static_cast<StreamPolicy>( flow->ssn_policy ) : tcpssn->client.config->policy;
- StreamPolicy server_os_policy = flow->ssn_policy ?
- static_cast<StreamPolicy>( flow->ssn_policy ) : tcpssn->server.config->policy;
-
- if( tcpssn->client.normalizer == nullptr )
- tcpssn->client.normalizer = TcpNormalizerFactory::create( client_os_policy, tcpssn,
- &tcpssn->client, &tcpssn->server );
-
- if( tcpssn->server.normalizer == nullptr )
- tcpssn->server.normalizer = TcpNormalizerFactory::create( server_os_policy, tcpssn,
- &tcpssn->server, &tcpssn->client );
-
- if( tcpssn->client.reassembler == nullptr )
- tcpssn->client.reassembler = TcpReassemblerFactory::create( tcpssn, &tcpssn->client, client_os_policy, false );
-
- if( tcpssn->server.reassembler == nullptr )
- tcpssn->server.reassembler = TcpReassemblerFactory::create( tcpssn, &tcpssn->server, server_os_policy, true );
-}
-
-/* Use a for loop and byte comparison, which has proven to be
- * faster on pipelined architectures compared to a memcmp (setup
- * for memcmp is slow). Not using a 4 byte and 2 byte long because
- * there is no guarantee of memory alignment (and thus performance
- * issues similar to memcmp). */
-static inline int ValidMacAddress(TcpTracker *talker, TcpTracker *listener, Packet *p)
-{
- int i, j, ret = 0;
-
- if (!(p->proto_bits & PROTO_BIT__ETH))
- return 0;
-
- // if flag is set, gauranteed to have an eth layer
- const eth::EtherHdr* eh = layer::get_eth_layer(p);
-
- for (i = 0; i < 6; ++i)
- {
- if ((talker->mac_addr[i] != eh->ether_src[i]))
- break;
- }
- for (j = 0; j < 6; ++j)
- {
- if (listener->mac_addr[j] != eh->ether_dst[j])
- break;
- }
-
- // FIXIT-L make this swap check configurable
- if (i < 6 && j < 6)
- {
- if (!memcmp(talker->mac_addr, eh->ether_dst, 6)
- && !memcmp(listener->mac_addr, eh->ether_src, 6))
- // this is prolly a tap
- return 0;
- }
-
- if (i < 6)
- {
- if (p->packet_flags & PKT_FROM_CLIENT)
- ret |= EVENT_SESSION_HIJACK_CLIENT;
- else
- ret |= EVENT_SESSION_HIJACK_SERVER;
- }
- if (j < 6)
- {
- if (p->packet_flags & PKT_FROM_CLIENT)
- ret |= EVENT_SESSION_HIJACK_SERVER;
- else
- ret |= EVENT_SESSION_HIJACK_CLIENT;
- }
- return ret;
-}
-
-static inline void CopyMacAddr(Packet* p, TcpSession* tcpssn, int dir)
-{
- int i;
-
- /* Not ethernet based, nothing to do */
- if (!(p->proto_bits & PROTO_BIT__ETH))
- return;
-
- // if flag is set, gauranteed to have an eth layer
- const eth::EtherHdr* eh = layer::get_eth_layer(p);
-
- if (dir == FROM_CLIENT)
- {
- /* Client is SRC */
- for (i = 0; i < 6; i++)
- {
- tcpssn->client.mac_addr[i] = eh->ether_src[i];
- tcpssn->server.mac_addr[i] = eh->ether_dst[i];
- }
- }
- else
- {
- /* Server is SRC */
- for (i = 0; i < 6; i++)
- {
- tcpssn->server.mac_addr[i] = eh->ether_src[i];
- tcpssn->client.mac_addr[i] = eh->ether_dst[i];
- }
- }
-}
-
-static void NewTcpSession(Packet* p, Flow* flow, StreamTcpConfig* dstPolicy, TcpSession* tss)
-{
- Inspector* ins = flow->gadget;
-
- if (!ins)
- ins = flow->clouseau;
-
- if (ins)
- {
- stream.set_splitter(flow, true, ins->get_splitter(true));
- stream.set_splitter(flow, false, ins->get_splitter(false));
- }
- else
- {
- stream.set_splitter(flow, true, new AtomSplitter(true));
- stream.set_splitter(flow, false, new AtomSplitter(false));
- }
-
- {
- DebugMessage(DEBUG_STREAM_STATE, "adding TcpSession to lightweight session\n");
- flow->protocol = p->type();
- tss->flow = flow;
-
- /* New session, previous was marked as reset. Clear the reset flag. */
- uint32_t session_flags = flow->clear_session_flags( SSNFLAG_RESET );
- if ((session_flags & SSNFLAG_CLIENT_SWAP) && !(session_flags & SSNFLAG_CLIENT_SWAPPED))
- {
- TcpTracker trk = tss->client;
- sfip_t ip = flow->client_ip;
- uint16_t port = flow->client_port;
-
- tss->client = tss->server;
- tss->server = trk;
-
- flow->client_ip = flow->server_ip;
- flow->server_ip = ip;
-
- flow->client_port = flow->server_port;
- flow->server_port = port;
-
- if (!flow->two_way_traffic())
- {
- if (session_flags & SSNFLAG_SEEN_CLIENT)
- {
- session_flags ^= SSNFLAG_SEEN_CLIENT;
- session_flags |= SSNFLAG_SEEN_SERVER;
- }
- else if (session_flags & SSNFLAG_SEEN_SERVER)
- {
- session_flags ^= SSNFLAG_SEEN_SERVER;
- session_flags |= SSNFLAG_SEEN_CLIENT;
- }
- }
-
- session_flags |= SSNFLAG_CLIENT_SWAPPED;
- flow->update_session_flags( session_flags );
- }
- init_flush_policy(flow, &tss->server);
- init_flush_policy(flow, &tss->client);
-
-#ifdef DEBUG_STREAM_EX
- PrintTcpSession(tss);
-#endif
- flow->set_expire(p, dstPolicy->session_timeout);
-
- AddStreamSession(&sfBase,
- flow->session_state & STREAM_STATE_MIDSTREAM ? SSNFLAG_MIDSTREAM : 0);
-
- StreamUpdatePerfBaseState(&sfBase, tss->flow, TCP_STATE_SYN_SENT);
-
- EventInternal(INTERNAL_EVENT_SESSION_ADD);
-
- tss->ecn = 0;
- assert(!tss->tcp_init);
- tss->tcp_init = true;
-
- tcpStats.trackers_created++;
- }
-}
-
-static void NewTcpSessionOnSyn(Flow* flow, TcpDataBlock* tdb, StreamTcpConfig* dstPolicy)
-{
- Profile profile(s5TcpNewSessPerfStats);
-
- const tcp::TCPHdr* tcph = tdb->pkt->ptrs.tcph;
- TcpSession* tss;
-
- /******************************************************************
- * start new sessions on proper SYN packets
- *****************************************************************/
- tss = (TcpSession*) flow->session;
- DebugMessage(DEBUG_STREAM_STATE, "Creating new session tracker on SYN!\n");
-
- flow->set_session_flags( SSNFLAG_SEEN_CLIENT );
-
- if (tcph->are_flags_set(TH_CWR | TH_ECE))
- flow->set_session_flags( SSNFLAG_ECN_CLIENT_QUERY );
-
- /* setup the stream trackers */
- /* Set the StreamTcpConfig for each direction (pkt from client) */
- tss->client.config = dstPolicy; // FIXIT-M use external binding for both dirs
- tss->server.config = dstPolicy; // (applies to all the blocks in this funk)
- set_os_policy(flow, tss);
-
- tss->client.s_mgr.state = TCP_STATE_SYN_SENT;
- tss->client.isn = tdb->seq;
- tss->client.l_unackd = tdb->seq + 1;
- tss->client.l_nxt_seq = tss->client.l_unackd;
-
- if (tdb->seq != tdb->end_seq)
- tss->client.l_nxt_seq += (tdb->end_seq - tdb->seq - 1);
-
- tss->client.l_window = tdb->win;
- tss->client.ts_last_pkt = tdb->pkt->pkth->ts.tv_sec;
-
- tss->server.reassembler->set_seglist_base_seq( tss->client.l_unackd );
- tss->server.r_nxt_ack = tss->client.l_unackd;
- tss->server.r_win_base = tdb->seq + 1;
- tss->server.s_mgr.state = TCP_STATE_LISTEN;
-
- tss->client.flags |= tss->client.normalizer->get_tcp_timestamp(tdb, false);
- tss->client.ts_last = tdb->ts;
- if (tss->client.ts_last == 0)
- tss->client.flags |= TF_TSTAMP_ZERO;
- tss->client.flags |= StreamGetMss(tdb->pkt, &tss->client.mss);
- tss->client.flags |= StreamGetWscale(tdb->pkt, &tss->client.wscale);
-
- CopyMacAddr(tdb->pkt, tss, FROM_CLIENT);
-
- tcpStats.sessions_on_syn++;
- NewTcpSession(tdb->pkt, flow, dstPolicy, tss);
-}
-
-static void NewTcpSessionOnSynAck(Flow* flow, TcpDataBlock* tdb, StreamTcpConfig* dstPolicy)
-{
- Profile profile(s5TcpNewSessPerfStats);
-
- const tcp::TCPHdr* tcph = tdb->pkt->ptrs.tcph;
- TcpSession* tss;
-
- tss = (TcpSession*) flow->session;
- DebugMessage(DEBUG_STREAM_STATE, "Creating new session tracker on SYN_ACK!\n");
-
- flow->set_session_flags( SSNFLAG_SEEN_SERVER );
- if (tcph->are_flags_set(TH_CWR | TH_ECE))
- flow->set_session_flags( SSNFLAG_ECN_SERVER_REPLY );
-
- /* setup the stream trackers */
- /* Set the config for each direction (pkt from server) */
- tss->server.config = dstPolicy;
- tss->client.config = dstPolicy;
- set_os_policy(flow, tss);
-
- tss->server.s_mgr.state = TCP_STATE_SYN_RCVD;
- tss->server.isn = tdb->seq;
- tss->server.l_unackd = tdb->seq + 1;
- tss->server.l_nxt_seq = tss->server.l_unackd;
- tss->server.l_window = tdb->win;
-
- tss->server.reassembler->set_seglist_base_seq( tdb->ack );
- tss->server.r_win_base = tdb->ack;
- tss->server.r_nxt_ack = tdb->ack;
- tss->server.ts_last_pkt = tdb->pkt->pkth->ts.tv_sec;
-
- tss->client.reassembler->set_seglist_base_seq( tss->server.l_unackd );
- tss->client.r_nxt_ack = tss->server.l_unackd;
- tss->client.r_win_base = tdb->seq + 1;
- tss->client.l_nxt_seq = tdb->ack;
- tss->client.isn = tdb->ack - 1;
- tss->client.s_mgr.state = TCP_STATE_SYN_SENT;
-
- tss->server.flags |= tss->server.normalizer->get_tcp_timestamp(tdb, false);
- tss->server.ts_last = tdb->ts;
- if (tss->server.ts_last == 0)
- tss->server.flags |= TF_TSTAMP_ZERO;
- tss->server.flags |= StreamGetMss(tdb->pkt, &tss->server.mss);
- tss->server.flags |= StreamGetWscale(tdb->pkt, &tss->server.wscale);
-
- CopyMacAddr(tdb->pkt, tss, FROM_SERVER);
-
- tcpStats.sessions_on_syn_ack++;
- NewTcpSession(tdb->pkt, flow, dstPolicy, tss);
-}
-
-static void NewTcpSessionOn3Way(Flow* flow, TcpDataBlock* tdb,
- StreamTcpConfig* dstPolicy)
-{
- Profile profile(s5TcpNewSessPerfStats);
-
- const tcp::TCPHdr* tcph = tdb->pkt->ptrs.tcph;
- TcpSession* tss;
-
- /******************************************************************
- * start new sessions on completion of 3-way (ACK only, no data)
- *****************************************************************/
- tss = ( TcpSession* ) flow->session;
- DebugMessage(DEBUG_STREAM_STATE, "Creating new session tracker on ACK!\n");
-
- flow->set_session_flags( SSNFLAG_SEEN_CLIENT );
-
- if (tcph->are_flags_set(TH_CWR | TH_ECE))
- flow->set_session_flags( SSNFLAG_ECN_CLIENT_QUERY );
-
- /* setup the stream trackers */
- /* Set the config for each direction (pkt from client) */
- tss->client.config = dstPolicy;
- tss->server.config = dstPolicy;
- set_os_policy( flow, tss );
-
- tss->client.s_mgr.state = TCP_STATE_ESTABLISHED;
- tss->client.isn = tdb->seq;
- tss->client.l_unackd = tdb->seq + 1;
- tss->client.l_nxt_seq = tss->client.l_unackd;
- tss->client.l_window = tdb->win;
-
- tss->client.ts_last_pkt = tdb->pkt->pkth->ts.tv_sec;
-
- tss->server.reassembler->set_seglist_base_seq( tss->client.l_unackd );
- tss->server.r_nxt_ack = tss->client.l_unackd;
- tss->server.r_win_base = tdb->seq + 1;
- tss->server.s_mgr.state = TCP_STATE_ESTABLISHED;
-
- tss->client.flags |= tss->client.normalizer->get_tcp_timestamp(tdb, false);
- tss->client.ts_last = tdb->ts;
- if (tss->client.ts_last == 0)
- tss->client.flags |= TF_TSTAMP_ZERO;
- tss->client.flags |= StreamGetMss(tdb->pkt, &tss->client.mss);
- tss->client.flags |= StreamGetWscale(tdb->pkt, &tss->client.wscale);
-
- CopyMacAddr(tdb->pkt, tss, FROM_CLIENT);
-
- tcpStats.sessions_on_3way++;
- NewTcpSession(tdb->pkt, flow, dstPolicy, tss);
-}
-
-static void NewTcpSessionOnData(Flow* flow, TcpDataBlock* tdb, StreamTcpConfig* dstPolicy)
-{
- Profile profile(s5TcpNewSessPerfStats);
-
- const tcp::TCPHdr* tcph = tdb->pkt->ptrs.tcph;
- TcpSession* tss;
-
- tss = (TcpSession*) flow->session;
- DebugMessage(DEBUG_STREAM_STATE, "Creating new session tracker on data packet (ACK|PSH)!\n");
-
- /* Set the config for each direction (pkt from client) */
- tss->client.config = dstPolicy;
- tss->server.config = dstPolicy;
- set_os_policy(flow, tss);
- if (flow->ssn_state.direction == FROM_CLIENT)
- {
- DebugMessage(DEBUG_STREAM_STATE, "Session direction is FROM_CLIENT\n");
-
- /* Sender is client (src port is higher) */
- flow->set_session_flags( SSNFLAG_SEEN_CLIENT );
- if (tcph->are_flags_set(TH_CWR | TH_ECE))
- flow->set_session_flags( SSNFLAG_ECN_CLIENT_QUERY );
-
- /* setup the stream trackers */
- tss->client.s_mgr.state = TCP_STATE_ESTABLISHED;
- tss->client.isn = tdb->seq;
- tss->client.l_unackd = tdb->seq;
- tss->client.l_nxt_seq = tss->client.l_unackd;
- tss->client.l_window = tdb->win;
-
- tss->client.ts_last_pkt = tdb->pkt->pkth->ts.tv_sec;
-
- tss->server.reassembler->set_seglist_base_seq( tss->client.l_unackd );
- tss->server.r_nxt_ack = tss->client.l_unackd;
- tss->server.r_win_base = tdb->seq;
- tss->server.l_window = 0; /* reset later */
-
- /* Next server packet is what was ACKd */
- //tss->server.l_nxt_seq = tdb->ack + 1;
- tss->server.l_unackd = tdb->ack - 1;
- tss->server.s_mgr.state = TCP_STATE_ESTABLISHED;
-
- tss->client.flags |= tss->client.normalizer->get_tcp_timestamp(tdb, false);
- tss->client.ts_last = tdb->ts;
- if (tss->client.ts_last == 0)
- tss->client.flags |= TF_TSTAMP_ZERO;
-
- tss->client.flags |= StreamGetMss(tdb->pkt, &tss->client.mss);
- tss->client.flags |= StreamGetWscale(tdb->pkt, &tss->client.wscale);
-
- CopyMacAddr(tdb->pkt, tss, FROM_CLIENT);
- }
- else
- {
- DebugMessage(DEBUG_STREAM_STATE, "Session direction is FROM_SERVER\n");
-
- /* Sender is server (src port is lower) */
- flow->set_session_flags( SSNFLAG_SEEN_SERVER );
-
- /* setup the stream trackers */
- tss->server.s_mgr.state = TCP_STATE_ESTABLISHED;
- tss->server.isn = tdb->seq;
- tss->server.l_unackd = tdb->seq;
- tss->server.l_nxt_seq = tss->server.l_unackd;
- tss->server.l_window = tdb->win;
-
- tss->server.reassembler->set_seglist_base_seq( tdb->ack );
- tss->server.r_win_base = tdb->ack;
- tss->server.r_nxt_ack = tdb->ack;
- tss->server.ts_last_pkt = tdb->pkt->pkth->ts.tv_sec;
-
- tss->client.reassembler->set_seglist_base_seq( tss->server.l_unackd );
- tss->client.r_nxt_ack = tss->server.l_unackd;
- tss->client.r_win_base = tdb->seq;
- tss->client.l_window = 0; /* reset later */
- tss->client.isn = tdb->ack - 1;
- tss->client.s_mgr.state = TCP_STATE_ESTABLISHED;
-
- tss->server.flags |= tss->server.normalizer->get_tcp_timestamp(tdb, 0);
- tss->server.ts_last = tdb->ts;
- if (tss->server.ts_last == 0)
- tss->server.flags |= TF_TSTAMP_ZERO;
-
- tss->server.flags |= StreamGetMss(tdb->pkt, &tss->server.mss);
- tss->server.flags |= StreamGetWscale(tdb->pkt, &tss->server.wscale);
-
- CopyMacAddr(tdb->pkt, tss, FROM_SERVER);
- }
-
- tcpStats.sessions_on_data++;
- NewTcpSession(tdb->pkt, flow, dstPolicy, tss);
-}
-
-static int ProcessTcp(Flow* flow, TcpDataBlock* tdb, StreamTcpConfig* config)
-{
- Profile profile(s5TcpStatePerfStats);
-
- int retcode = ACTION_NOTHING;
- int eventcode = 0;
- int got_ts = 0;
- int new_ssn = 0;
- int ts_action = ACTION_NOTHING;
- const tcp::TCPHdr* tcph = tdb->pkt->ptrs.tcph;
- TcpSession* tcpssn = NULL;
- TcpTracker* talker = NULL;
- TcpTracker* listener = NULL;
- DEBUG_WRAP( const char* t = NULL; const char* l = NULL; );
-
- if (flow->protocol != PktType::TCP)
- {
- DebugMessage(DEBUG_STREAM_STATE, "Lightweight session not TCP on TCP packet\n");
- return retcode;
- }
-
- tcpssn = ( TcpSession* ) flow->session;
-
- if (!tcpssn->tcp_init)
- {
- // FIXIT-L expected flow should be checked by flow_con before we
- // get here
- char ignore = flow_con->expected_flow(flow, tdb->pkt);
-
- if (ignore)
- {
- tcpssn->server.flush_policy = STREAM_FLPOLICY_IGNORE;
- tcpssn->client.flush_policy = STREAM_FLPOLICY_IGNORE;
- return retcode;
- }
-
- bool require3Way = config->require_3whs();
- bool allow_midstream = config->midstream_allowed(tdb->pkt);
-
- if (tcph->is_syn_only())
- {
- DebugMessage(DEBUG_STREAM_STATE, "Stream SYN PACKET, establishing lightweight session direction.\n");
- /* SYN packet from client */
- flow->ssn_state.direction = FROM_CLIENT;
- flow->session_state |= STREAM_STATE_SYN;
-
- if (require3Way || (StreamPacketHasWscale(tdb->pkt) & TF_WSCALE) || (tdb->pkt->dsize > 0))
- {
- /* Create TCP session if we
- * 1) require 3-WAY HS, OR
- * 2) client sent wscale option, OR
- * 3) have data
- */
- NewTcpSessionOnSyn( flow, tdb, config);
- new_ssn = 1;
- tcpssn->server.normalizer->ecn_tracker( (tcp::TCPHdr *) tcph, require3Way );
- }
-
- /* Nothing left todo here */
- }
- else if (tcph->is_syn_ack())
- {
- /* SYN-ACK from server */
- if ((flow->session_state == STREAM_STATE_NONE) || (flow->get_session_flags() & SSNFLAG_RESET))
- {
- DebugMessage(DEBUG_STREAM_STATE, "Stream SYN|ACK PACKET, establishing lightweight session direction.\n");
- flow->ssn_state.direction = FROM_SERVER;
- }
-
- flow->session_state |= STREAM_STATE_SYN_ACK;
-
- if (!require3Way || allow_midstream)
- {
- NewTcpSessionOnSynAck(flow, tdb, config);
- new_ssn = 1;
- }
-
- tcpssn->client.normalizer->ecn_tracker( (tcp::TCPHdr *) tcph, require3Way );
- }
- else if (tcph->is_ack() && !tcph->is_rst() && (flow->session_state & STREAM_STATE_SYN_ACK))
- {
- /* FIXIT: do we need to verify the ACK field is >= the seq of the SYN-ACK?
- 3-way Handshake complete, create TCP session */
- flow->session_state |= STREAM_STATE_ACK | STREAM_STATE_ESTABLISHED;
- NewTcpSessionOn3Way(flow, tdb, config);
- new_ssn = 1;
- tcpssn->server.normalizer->ecn_tracker( (tcp::TCPHdr *) tcph, require3Way );
- StreamUpdatePerfBaseState(&sfBase, flow, TCP_STATE_ESTABLISHED);
- }
- else if (tdb->pkt->dsize && (!require3Way || allow_midstream))
- {
- /* create session on data, need to figure out direction, etc
- Assume from client, can update later */
- if (tdb->pkt->ptrs.sp > tdb->pkt->ptrs.dp)
- flow->ssn_state.direction = FROM_CLIENT;
- else
- flow->ssn_state.direction = FROM_SERVER;
+ static_cast<StreamPolicy>( flow->ssn_policy ) : config->policy;
+ StreamPolicy server_os_policy = flow->ssn_policy ?
+ static_cast<StreamPolicy>( flow->ssn_policy ) : config->policy;
- flow->session_state |= STREAM_STATE_MIDSTREAM;
- flow->set_session_flags( SSNFLAG_MIDSTREAM );
+ if ( client->normalizer == nullptr )
+ client->normalizer = TcpNormalizerFactory::create(this, client_os_policy, client, server);
- NewTcpSessionOnData(flow, tdb, config);
- new_ssn = 1;
- if(flow->ssn_state.direction == FROM_CLIENT)
- tcpssn->server.normalizer->ecn_tracker( (tcp::TCPHdr *) tcph, require3Way );
- else
- tcpssn->client.normalizer->ecn_tracker( (tcp::TCPHdr *) tcph, require3Way );
+ if ( server->normalizer == nullptr )
+ server->normalizer = TcpNormalizerFactory::create(this, server_os_policy, server, client);
- if (flow->session_state & STREAM_STATE_ESTABLISHED)
- StreamUpdatePerfBaseState(&sfBase, flow, TCP_STATE_ESTABLISHED);
- }
- else if (!tdb->pkt->dsize)
- {
- // Do nothing.
- return retcode;
- }
- }
- else
+ if ( client->reassembler == nullptr )
+ client->reassembler = TcpReassemblerFactory::create(this, client, client_os_policy, false);
+
+ if ( server->reassembler == nullptr )
+ server->reassembler = TcpReassemblerFactory::create(this, server, server_os_policy, true);
+}
+
+// FIXIT - check for need to swap client/server is ifdef'ed out...
+void TcpSession::swap_trackers(void)
+{
+ uint32_t session_flags = flow->get_session_flags( );
+ if ( ( session_flags & SSNFLAG_CLIENT_SWAP ) && !( session_flags & SSNFLAG_CLIENT_SWAPPED ) )
{
- /* If session is already marked as established */
- if (!(flow->session_state & STREAM_STATE_ESTABLISHED)
- && (!config->require_3whs() || config->midstream_allowed(tdb->pkt)))
- {
- /* If not requiring 3-way Handshake... */
+ TcpTracker* trk = client;
+ client = server;
+ server = trk;
- /* TCP session created on TH_SYN above,
- * or maybe on SYN-ACK, or anything else */
+ sfip_t ip = flow->client_ip;
+ flow->client_ip = flow->server_ip;
+ flow->server_ip = ip;
- /* Need to update Lightweight session state */
- if (tcph->is_syn_ack())
+ uint16_t port = flow->client_port;
+ flow->client_port = flow->server_port;
+ flow->server_port = port;
+
+ if ( !flow->two_way_traffic() )
+ {
+ if ( session_flags & SSNFLAG_SEEN_CLIENT )
{
- /* SYN-ACK from server */
- if (flow->session_state != STREAM_STATE_NONE)
- {
- flow->session_state |= STREAM_STATE_SYN_ACK;
- }
+ session_flags ^= SSNFLAG_SEEN_CLIENT;
+ session_flags |= SSNFLAG_SEEN_SERVER;
}
- else if (tcph->is_ack() && (flow->session_state & STREAM_STATE_SYN_ACK))
+ else if ( session_flags & SSNFLAG_SEEN_SERVER )
{
- flow->session_state |= STREAM_STATE_ACK | STREAM_STATE_ESTABLISHED;
- StreamUpdatePerfBaseState(&sfBase, flow, TCP_STATE_ESTABLISHED);
+ session_flags ^= SSNFLAG_SEEN_SERVER;
+ session_flags |= SSNFLAG_SEEN_CLIENT;
}
}
- if (tcph->is_syn())
- tcpssn->server.normalizer->ecn_tracker( (tcp::TCPHdr *) tcph, config->require_3whs() );
+
+ session_flags |= SSNFLAG_CLIENT_SWAPPED;
+ flow->update_session_flags(session_flags);
}
+}
- if (tdb->pkt->packet_flags & PKT_FROM_SERVER)
- {
- DebugMessage(DEBUG_STREAM_STATE, "Stream: Updating on packet from server\n");
- flow->set_session_flags( SSNFLAG_SEEN_SERVER );
+void TcpSession::init_new_tcp_session(TcpSegmentDescriptor& tsd)
+{
+ flow->protocol = tsd.get_pkt()->type();
- if (tcpssn->tcp_init)
- {
- talker = &tcpssn->server;
- listener = &tcpssn->client;
- }
+ /* New session, previous was marked as reset. Clear the reset flag. */
+ flow->clear_session_flags(SSNFLAG_RESET);
+ flow->set_expire(tsd.get_pkt(), config->session_timeout);
+ AddStreamSession(&sfBase, flow->session_state & STREAM_STATE_MIDSTREAM ? SSNFLAG_MIDSTREAM : 0);
+ update_perf_base_state(&sfBase, TcpStreamTracker::TCP_SYN_SENT);
+ tel->EventInternal(INTERNAL_EVENT_SESSION_ADD);
- DEBUG_WRAP(
- t = "Server";
- l = "Client");
+ //assert( !tcp_init );
+ tcp_init = true;
+ new_ssn = true;
- if( talker && ( talker->s_mgr.state == TCP_STATE_LISTEN ) && tcph->is_syn_only() )
- eventcode |= EVENT_4WHS;
+ // FIXIT - this state is bogus... move to tracker init...
+ tcpStats.trackers_created++;
+}
- /* If we picked this guy up midstream, finish the initialization */
- if ((flow->session_state & STREAM_STATE_MIDSTREAM) && !(flow->session_state & STREAM_STATE_ESTABLISHED))
- {
- FinishServerInit(tdb, tcpssn);
- if( tcph->are_flags_set( TH_ECE ) && ( flow->get_session_flags() & SSNFLAG_ECN_CLIENT_QUERY ) )
- flow->set_session_flags( SSNFLAG_ECN_SERVER_REPLY );
+void TcpSession::NewTcpSessionOnSyn(TcpSegmentDescriptor& tsd)
+{
+ server->init_on_syn_recv(tsd);
+ client->init_on_syn_sent(tsd);
+ init_new_tcp_session(tsd);
+ tcpStats.sessions_on_syn++;
+}
+
+void TcpSession::NewTcpSessionOnSynAck(TcpSegmentDescriptor& tsd)
+{
+ server->init_on_synack_sent(tsd);
+ client->init_on_synack_recv(tsd);
+ init_new_tcp_session(tsd);
+ tcpStats.sessions_on_syn_ack++;
+}
- if( flow->get_session_flags() & SSNFLAG_SEEN_CLIENT )
+void TcpSession::update_session_state(const tcp::TCPHdr* tcph, TcpSegmentDescriptor& tsd)
+{
+ /* If session is already marked as established */
+ if (!(flow->session_state & STREAM_STATE_ESTABLISHED)
+ && (!require_3whs || config->midstream_allowed(tsd.get_pkt())))
+ {
+ /* If not requiring 3-way Handshake...
+ TCP session created on TH_SYN above, or maybe on SYN-ACK, or anything else
+ Need to update Lightweight session state */
+ if (tcph->is_syn_ack())
+ {
+ /* SYN-ACK from server */
+ if (flow->session_state != STREAM_STATE_NONE)
{
- // should TCP state go to established too?
- flow->session_state |= STREAM_STATE_ESTABLISHED;
- flow->set_session_flags( SSNFLAG_ESTABLISHED );
- StreamUpdatePerfBaseState( &sfBase, flow, TCP_STATE_ESTABLISHED );
+ flow->session_state |= STREAM_STATE_SYN_ACK;
}
}
- if (!flow->inner_server_ttl)
- flow->set_ttl(tdb->pkt, false);
+ else if (tcph->is_ack() && (flow->session_state & STREAM_STATE_SYN_ACK))
+ {
+ flow->session_state |= STREAM_STATE_ACK | STREAM_STATE_ESTABLISHED;
+ update_perf_base_state(&sfBase, TcpStreamTracker::TCP_ESTABLISHED);
+ }
}
- else
+}
+
+void TcpSession::update_session_on_server_packet(const tcp::TCPHdr* tcph,
+ TcpSegmentDescriptor& tsd)
+{
+ DebugMessage(DEBUG_STREAM_STATE, "Stream: Updating on packet from server\n");
+
+ flow->set_session_flags(SSNFLAG_SEEN_SERVER);
+ if (tcp_init)
+ {
+ talker = server;
+ listener = client;
+ }
+
+ if (talker && (talker->get_tcp_state() == TcpStreamTracker::TCP_LISTEN) && tcph->is_syn_only())
+ tel->set_tcp_event(EVENT_4WHS);
+
+ /* If we picked this guy up midstream, finish the initialization */
+ if ((flow->session_state & STREAM_STATE_MIDSTREAM) && !(flow->session_state &
+ STREAM_STATE_ESTABLISHED))
{
- DebugMessage(DEBUG_STREAM_STATE, "Stream: Updating on packet from client\n");
- /* if we got here we had to see the SYN already... */
- flow->set_session_flags( SSNFLAG_SEEN_CLIENT );
- if (tcpssn->tcp_init)
+ FinishServerInit(tsd);
+ if (tcph->are_flags_set(TH_ECE) && (flow->get_session_flags() & SSNFLAG_ECN_CLIENT_QUERY))
+ flow->set_session_flags(SSNFLAG_ECN_SERVER_REPLY);
+
+ if (flow->get_session_flags() & SSNFLAG_SEEN_CLIENT)
{
- talker = &tcpssn->client;
- listener = &tcpssn->server;
+ // should TCP state go to established too?
+ flow->session_state |= STREAM_STATE_ESTABLISHED;
+ flow->set_session_flags(SSNFLAG_ESTABLISHED);
+ update_perf_base_state(&sfBase, TcpStreamTracker::TCP_ESTABLISHED);
}
+ }
+
+ if (!flow->inner_server_ttl)
+ flow->set_ttl(tsd.get_pkt(), false);
+}
+
+void TcpSession::update_session_on_client_packet(TcpSegmentDescriptor& tsd)
+{
+ DebugMessage(DEBUG_STREAM_STATE, "Stream: Updating on packet from client\n");
- DEBUG_WRAP(
- t = "Server";
- l = "Client");
+ /* if we got here we had to see the SYN already... */
+ flow->set_session_flags(SSNFLAG_SEEN_CLIENT);
+ if (tcp_init)
+ {
+ talker = client;
+ listener = server;
+ }
- if ((flow->session_state & STREAM_STATE_MIDSTREAM) && !(flow->session_state & STREAM_STATE_ESTABLISHED))
+ if ((flow->session_state & STREAM_STATE_MIDSTREAM)
+ && !(flow->session_state & STREAM_STATE_ESTABLISHED))
+ {
+ /* Midstream and seen server. */
+ if (flow->get_session_flags() & SSNFLAG_SEEN_SERVER)
{
- /* Midstream and seen server. */
- if (flow->get_session_flags() & SSNFLAG_SEEN_SERVER)
- {
- flow->session_state |= STREAM_STATE_ESTABLISHED;
- flow->set_session_flags( SSNFLAG_ESTABLISHED );
- }
+ flow->session_state |= STREAM_STATE_ESTABLISHED;
+ flow->set_session_flags(SSNFLAG_ESTABLISHED);
}
- if (!flow->inner_client_ttl)
- flow->set_ttl(tdb->pkt, true);
}
- /*
- * check for SYN on reset session
- */
- if( ( flow->get_session_flags() & SSNFLAG_RESET ) && tcph->is_syn() )
+ if (!flow->inner_client_ttl)
+ flow->set_ttl(tsd.get_pkt(), true);
+}
+
+bool TcpSession::handle_syn_on_reset_session(const tcp::TCPHdr* tcph, TcpSegmentDescriptor& tsd)
+{
+ if ( !tcp_init || ( listener->get_tcp_state() == TcpStreamTracker::TCP_CLOSED )
+ || ( talker->get_tcp_state() == TcpStreamTracker::TCP_CLOSED ) )
{
- if ( !tcpssn->tcp_init || ( listener->s_mgr.state == TCP_STATE_CLOSED )
- || ( talker->s_mgr.state == TCP_STATE_CLOSED ) )
- {
- /* Listener previously issued a reset
- Talker is re-SYN-ing */
- // FIXIT-L this leads to bogus 129:20
- TcpSessionCleanup(flow, 1);
+ /* Listener previously issued a reset Talker is re-SYN-ing */
+ // FIXIT-L this leads to bogus 129:20
+ cleanup_session(1);
- if( tcph->is_rst() )
- {
- /* FIXIT-M In inline mode, only one of the normalizations
- * can occur. If the first normalization
- * fires, there is nothing for the second normalization
- * to do. However, in inline-test mode, since
- * nothing is actually normalized, both of the
- * following functions report that they 'would'
- * normalize. i.e., both functions increment their
- * count even though only one function can ever
- * perform a normalization.
- */
+ if ( tcph->is_rst() )
+ {
+ /* FIXIT-M In inline mode, only one of the normalizations
+ * can occur. If the first normalization
+ * fires, there is nothing for the second normalization
+ * to do. However, in inline-test mode, since
+ * nothing is actually normalized, both of the
+ * following functions report that they 'would'
+ * normalize. i.e., both functions increment their
+ * count even though only one function can ever
+ * perform a normalization.
+ */
- /* Got SYN/RST. We're done. */
- listener->normalizer->trim_syn_payload( tdb );
- listener->normalizer->trim_rst_payload( tdb );
- return retcode | ACTION_RST;
- }
- else if (tcph->is_syn_only())
+ /* Got SYN/RST. We're done. */
+ listener->normalizer->trim_syn_payload(tsd);
+ listener->normalizer->trim_rst_payload(tsd);
+ pkt_action_mask |= ACTION_RST;
+ return false;
+ }
+ else if (tcph->is_syn_only())
+ {
+ flow->ssn_state.direction = FROM_CLIENT;
+ flow->session_state = STREAM_STATE_SYN;
+ flow->set_ttl(tsd.get_pkt(), true);
+ NewTcpSessionOnSyn(tsd);
+ tcpStats.resyns++;
+ listener = server;
+ talker = client;
+ listener->normalizer->ecn_tracker( (tcp::TCPHdr*)tcph, require_3whs);
+ flow->update_session_flags(SSNFLAG_SEEN_CLIENT);
+ }
+ else if (tcph->is_syn_ack())
+ {
+ if (config->midstream_allowed(tsd.get_pkt()))
{
- flow->ssn_state.direction = FROM_CLIENT;
- flow->session_state = STREAM_STATE_SYN;
- flow->set_ttl(tdb->pkt, true);
- NewTcpSessionOnSyn( flow, tdb, config);
+ flow->ssn_state.direction = FROM_SERVER;
+ flow->session_state = STREAM_STATE_SYN_ACK;
+ flow->set_ttl(tsd.get_pkt(), false);
+ NewTcpSessionOnSynAck(tsd);
tcpStats.resyns++;
- new_ssn = 1;
-
- bool require3Way = config->require_3whs();
- listener = &tcpssn->server;
- talker = &tcpssn->client;
- listener->normalizer->ecn_tracker( (tcp::TCPHdr *) tcph, require3Way );
- flow->update_session_flags( SSNFLAG_SEEN_CLIENT );
}
- else if (tcph->is_syn_ack())
- {
- if (config->midstream_allowed(tdb->pkt))
- {
- flow->ssn_state.direction = FROM_SERVER;
- flow->session_state = STREAM_STATE_SYN_ACK;
- flow->set_ttl(tdb->pkt, false);
- NewTcpSessionOnSynAck( flow, tdb, config);
- tcpStats.resyns++;
- tcpssn = (TcpSession*) flow->session;
- new_ssn = 1;
- }
- bool require3Way = config->require_3whs();
- listener = &tcpssn->client;
- talker = &tcpssn->server;
- listener->normalizer->ecn_tracker( (tcp::TCPHdr *) tcph, require3Way );
- flow->update_session_flags( SSNFLAG_SEEN_SERVER );
- }
+ listener = client;
+ talker = server;
+ listener->normalizer->ecn_tracker( (tcp::TCPHdr*)tcph, require_3whs);
+ flow->update_session_flags(SSNFLAG_SEEN_SERVER);
}
-
- DebugMessage(DEBUG_STREAM_STATE, "Got SYN pkt on reset ssn, re-SYN-ing\n");
}
+ DebugMessage(DEBUG_STREAM_STATE, "Got SYN pkt on reset ssn, re-SYN-ing\n");
+
+ return true;
+}
+
+void TcpSession::update_ignored_session(TcpSegmentDescriptor& tsd)
+{
// 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_session(flow, tdb->pkt))
+ if (stream.ignored_session(flow, tsd.get_pkt()))
{
if (talker && (talker->flags & TF_FORCE_FLUSH))
{
- tcpssn->flush_talker(tdb->pkt);
+ flush_talker(tsd.get_pkt());
talker->flags &= ~TF_FORCE_FLUSH;
}
if (listener && (listener->flags & TF_FORCE_FLUSH))
{
- tcpssn->flush_listener(tdb->pkt);
+ flush_listener(tsd.get_pkt());
listener->flags &= ~TF_FORCE_FLUSH;
}
- tdb->pkt->packet_flags |= PKT_IGNORE;
- retcode |= ACTION_DISABLE_INSPECTION;
+ tsd.get_pkt()->packet_flags |= PKT_IGNORE;
+ pkt_action_mask |= ACTION_DISABLE_INSPECTION;
}
+}
+void TcpSession::handle_data_on_syn(const tcp::TCPHdr* tcph, TcpSegmentDescriptor& tsd)
+{
/* Handle data on SYN */
- if ((tdb->pkt->dsize) && tcph->is_syn())
+ if ((tsd.get_pkt()->dsize) && tcph->is_syn())
{
/* MacOS accepts data on SYN, so don't alert if policy is MACOS */
if (talker->normalizer->get_os_policy() != StreamPolicy::OS_MACOS)
{
// remove data on SYN
- listener->normalizer->trim_syn_payload( tdb );
+ listener->normalizer->trim_syn_payload(tsd);
if (Normalize_GetMode(NORM_TCP_TRIM_SYN) == NORM_MODE_OFF)
{
DebugMessage(DEBUG_STREAM_STATE, "Got data on SYN packet, not processing it\n");
//EventDataOnSyn(config);
- eventcode |= EVENT_DATA_ON_SYN;
- retcode |= ACTION_BAD_PKT;
+ tel->set_tcp_event(EVENT_DATA_ON_SYN);
+ pkt_action_mask |= ACTION_BAD_PKT;
}
}
}
+}
- if (!tcpssn->tcp_init)
+void TcpSession::process_tcp_packet(TcpSegmentDescriptor& tsd)
+{
+ Profile profile(s5TcpStatePerfStats);
+
+ int got_ts = 0;
+ talker = nullptr;
+ listener = nullptr;
+ const tcp::TCPHdr* tcph = tsd.get_tcph();
+
+ DEBUG_WRAP(const char* t = NULL; const char* l = NULL; );
+
+ /* If session is already marked as established */
+ update_session_state(tcph, tsd);
+
+ if ( tcph->is_syn() )
+ server->normalizer->ecn_tracker( (tcp::TCPHdr*)tcph, config->require_3whs() );
+
+ if ( tsd.get_pkt()->packet_flags & PKT_FROM_SERVER )
{
- LogTcpEvents(eventcode);
- return retcode;
+ update_session_on_server_packet(tcph, tsd);
+ DEBUG_WRAP(t = "Server"; l = "Client");
}
+ else
+ {
+ update_session_on_client_packet(tsd);
+ DEBUG_WRAP(t = "Server"; l = "Client");
+ }
+
+ //check for SYN on reset session
+ if ( ( flow->get_session_flags() & SSNFLAG_RESET ) && tcph->is_syn() )
+ if ( !handle_syn_on_reset_session(tcph, tsd) )
+ return;
+
+ update_ignored_session(tsd);
+
+ handle_data_on_syn(tcph, tsd);
+
+ if (!tcp_init)
+ return;
- DebugFormat(DEBUG_STREAM_STATE, " %s [talker] state: %s\n", t, state_names[talker->s_mgr.state]);
- DebugFormat(DEBUG_STREAM_STATE, " %s state: %s(%d)\n", l, state_names[listener->s_mgr.state], listener->s_mgr.state);
+ DebugFormat(DEBUG_STREAM_STATE, " %s [talker] state: %s\n", t,
+ tcp_state_names[talker->get_tcp_state()]);
+ DebugFormat(DEBUG_STREAM_STATE, " %s state: %s(%d)\n", l,
+ tcp_state_names[listener->get_tcp_state()], listener->get_tcp_state());
// may find better placement to eliminate redundant flag checks
- if( tcph->is_syn() )
+ if ( tcph->is_syn() )
talker->s_mgr.sub_state |= SUB_SYN_SENT;
- if( tcph->is_ack() )
+ if ( tcph->is_ack() )
talker->s_mgr.sub_state |= SUB_ACK_SENT;
- /*
- * process SYN ACK on unestablished sessions
- */
- if ((TCP_STATE_SYN_SENT == listener->s_mgr.state) && (TCP_STATE_LISTEN == talker->s_mgr.state))
+ // process SYN ACK on unestablished sessions
+ if ( ( TcpStreamTracker::TCP_SYN_SENT == listener->get_tcp_state() ) &&
+ ( TcpStreamTracker::TCP_LISTEN == talker->get_tcp_state() ) )
{
- if( tcph->is_ack() )
+ if ( tcph->is_ack() )
{
- /*
- * make sure we've got a valid segment
- */
- if (!IsBetween(listener->l_unackd, listener->l_nxt_seq, tdb->ack))
+ // make sure we've got a valid segment
+ if (!listener->is_ack_valid(tsd.get_ack() ) )
{
- DebugMessage(DEBUG_STREAM_STATE, "Pkt ack is out of bounds, bailing!\n");
+ DebugFormat(DEBUG_STREAM_STATE,
+ "Pkt Ack is Out of Bounds (%X, %X, %X) = (snd_una, snd_nxt, cur)\n",
+ listener->get_snd_una(), listener->get_snd_nxt(), tsd.get_ack());
inc_tcp_discards();
- listener->normalizer->trim_win_payload( tdb );
- LogTcpEvents(eventcode);
- return retcode | ACTION_BAD_PKT;
+ listener->normalizer->trim_win_payload(tsd);
+ pkt_action_mask |= ACTION_BAD_PKT;
+ return;
}
}
- talker->flags |= talker->normalizer->get_tcp_timestamp(tdb, false);
- if (tdb->ts == 0)
+ talker->flags |= talker->normalizer->get_tcp_timestamp(tsd, false);
+ if (tsd.get_ts() == 0)
talker->flags |= TF_TSTAMP_ZERO;
- /*
- * catch resets sent by server
- */
- if( tcph->is_rst() )
+ // catch resets sent by server
+ if ( tcph->is_rst() )
{
DebugMessage(DEBUG_STREAM_STATE, "got RST\n");
- listener->normalizer->trim_rst_payload( tdb );
+ listener->normalizer->trim_rst_payload(tsd);
- /* Reset is valid when in SYN_SENT if the
- * ack field ACKs the SYN.
- */
- if (ValidRstSynSent(listener, tdb))
+ // Reset is valid when in SYN_SENT if the ack field ACKs the SYN.
+ if ( listener->is_rst_valid_in_syn_sent(tsd) )
{
DebugMessage(DEBUG_STREAM_STATE, "got RST, closing talker\n");
/* Reset is valid */
* additional data sent from one side or the other isn't
* processed (and is dropped in inline mode).
*/
- flow->set_session_flags( SSNFLAG_RESET );
- talker->s_mgr.state = TCP_STATE_CLOSED;
- StreamUpdatePerfBaseState(&sfBase, flow, TCP_STATE_CLOSING);
+ flow->set_session_flags(SSNFLAG_RESET);
+ talker->set_tcp_state(TcpStreamTracker::TCP_CLOSED);
+ update_perf_base_state(&sfBase, TcpStreamTracker::TCP_CLOSING);
/* Leave listener open, data may be in transit */
- LogTcpEvents(eventcode);
- return retcode | ACTION_RST;
+ pkt_action_mask |= ACTION_RST;
+ return;
}
/* Reset not valid. */
DebugMessage(DEBUG_STREAM_STATE, "bad sequence number, bailing\n");
inc_tcp_discards();
- eventcode |= EVENT_BAD_RST;
- listener->normalizer->packet_dropper(tdb, NORM_TCP_BLOCK);
- LogTcpEvents(eventcode);
- return retcode;
+ tel->set_tcp_event(EVENT_BAD_RST);
+ listener->normalizer->packet_dropper(tsd, NORM_TCP_BLOCK);
+ return;
}
// finish up server init
- if( tcph->is_syn() )
+ if ( tcph->is_syn() )
{
- FinishServerInit(tdb, tcpssn);
+ FinishServerInit(tsd);
if (talker->flags & TF_TSTAMP)
{
- talker->ts_last_pkt = tdb->pkt->pkth->ts.tv_sec;
- talker->ts_last = tdb->ts;
+ talker->set_ts_last_packet(tsd.get_pkt()->pkth->ts.tv_sec);
+ talker->ts_last = tsd.get_ts();
}
DebugMessage(DEBUG_STREAM_STATE, "Finish server init got called!\n");
DebugMessage(DEBUG_STREAM_STATE, "Finish server init didn't get called!\n");
}
- if( tcph->are_flags_set( TH_ECE ) && ( flow->get_session_flags() & SSNFLAG_ECN_CLIENT_QUERY ) )
- flow->set_session_flags( SSNFLAG_ECN_SERVER_REPLY );
+ if ( tcph->are_flags_set(TH_ECE) &&
+ ( flow->get_session_flags() & SSNFLAG_ECN_CLIENT_QUERY ) )
+ flow->set_session_flags(SSNFLAG_ECN_SERVER_REPLY);
// explicitly set the state
- listener->s_mgr.state = TCP_STATE_SYN_SENT;
+ listener->set_tcp_state(TcpStreamTracker::TCP_SYN_SENT);
DebugMessage(DEBUG_STREAM_STATE, "Accepted SYN ACK\n");
- LogTcpEvents(eventcode);
- return retcode;
+ return;
}
/*
* This is per RFC 1323.
*/
if ((talker->flags & TF_WSCALE) && (listener->flags & TF_WSCALE))
- tdb->win <<= talker->wscale;
+ tsd.set_win(tsd.get_win() << talker->wscale);
/* Check for session hijacking -- compare mac address to the ones
* that were recorded at session startup. */
#ifdef DAQ_PKT_FLAG_PRE_ROUTING
- if (!(tdb->pkt->pkth->flags & DAQ_PKT_FLAG_PRE_ROUTING))
+ if (!(tsd.get_pkt()->pkth->flags & DAQ_PKT_FLAG_PRE_ROUTING))
#endif
{
- eventcode |= ValidMacAddress(talker, listener, tdb->pkt);
+ tel->set_tcp_event(is_mac_address_valid (talker, listener, tsd.get_pkt() ) );
}
- ts_action = listener->normalizer->handle_paws( tdb, &eventcode, &got_ts );
+ pkt_action_mask |= listener->normalizer->handle_paws(tsd, &got_ts);
// check RST validity
- if( tcph->is_rst() )
+ if ( tcph->is_rst() )
{
- listener->normalizer->trim_rst_payload( tdb );
+ listener->normalizer->trim_rst_payload(tsd);
- if (listener->normalizer->validate_rst( tdb ))
+ if (listener->normalizer->validate_rst(tsd))
{
DebugMessage(DEBUG_STREAM_STATE, "Got RST, bailing\n");
- if (listener->s_mgr.state == TCP_STATE_FIN_WAIT_1
- || listener->s_mgr.state == TCP_STATE_FIN_WAIT_2
- || listener->s_mgr.state == TCP_STATE_CLOSE_WAIT
- || listener->s_mgr.state == TCP_STATE_CLOSING)
+ if (listener->get_tcp_state() == TcpStreamTracker::TCP_FIN_WAIT1
+ || listener->get_tcp_state() == TcpStreamTracker::TCP_FIN_WAIT2
+ || listener->get_tcp_state() == TcpStreamTracker::TCP_CLOSE_WAIT
+ || listener->get_tcp_state() == TcpStreamTracker::TCP_CLOSING)
{
- tcpssn->flush_talker(tdb->pkt);
- tcpssn->flush_listener(tdb->pkt);
- tcpssn->set_splitter(true, nullptr);
- tcpssn->set_splitter(false, nullptr);
+ flush_talker(tsd.get_pkt());
+ flush_listener(tsd.get_pkt());
+ set_splitter(true, nullptr);
+ set_splitter(false, nullptr);
flow->free_application_data();
}
- flow->set_session_flags( SSNFLAG_RESET );
- talker->s_mgr.state = TCP_STATE_CLOSED;
- talker->s_mgr.sub_state |= SUB_RST_SENT;
- StreamUpdatePerfBaseState(&sfBase, flow, TCP_STATE_CLOSING);
- if( listener->normalizer->is_tcp_ips_enabled() )
- listener->s_mgr.state = TCP_STATE_CLOSED;
+ flow->set_session_flags(SSNFLAG_RESET);
+ talker->set_tcp_state(TcpStreamTracker::TCP_CLOSED);
+ talker->s_mgr.sub_state |= SUB_RST_SENT;
+ update_perf_base_state(&sfBase, TcpStreamTracker::TCP_CLOSING);
- /* else for ids:
- leave listener open, data may be in transit */
+ if ( listener->normalizer->is_tcp_ips_enabled() )
+ listener->set_tcp_state(TcpStreamTracker::TCP_CLOSED);
- LogTcpEvents(eventcode);
- return retcode | ACTION_RST;
+ /* else for ids: leave listener open, data may be in transit */
+ pkt_action_mask |= ACTION_RST;
+ return;
}
/* Reset not valid. */
DebugMessage(DEBUG_STREAM_STATE, "bad sequence number, bailing\n");
inc_tcp_discards();
- eventcode |= EVENT_BAD_RST;
- listener->normalizer->packet_dropper(tdb, NORM_TCP_BLOCK);
- LogTcpEvents(eventcode);
- return retcode | ts_action;
+ tel->set_tcp_event(EVENT_BAD_RST);
+ listener->normalizer->packet_dropper(tsd, NORM_TCP_BLOCK);
+ return;
}
else
{
/* check for valid seqeuence/retrans */
- if (listener->config->policy != StreamPolicy::OS_PROXY
- and (listener->s_mgr.state >= TCP_STATE_ESTABLISHED)
- and !ValidSeq( listener, tdb ))
+ if (config->policy != StreamPolicy::OS_PROXY
+ and (listener->get_tcp_state() >= TcpStreamTracker::TCP_ESTABLISHED)
+ and !ValidSeq(listener, tsd))
{
DebugMessage(DEBUG_STREAM_STATE, "bad sequence number, bailing\n");
inc_tcp_discards();
- listener->normalizer->trim_win_payload( tdb );
- LogTcpEvents(eventcode);
- return retcode | ts_action;
+ listener->normalizer->trim_win_payload(tsd);
+ return;
}
}
- if (ts_action != ACTION_NOTHING)
+ if ( pkt_action_mask & ACTION_BAD_PKT )
{
DebugMessage(DEBUG_STREAM_STATE, "bad timestamp, bailing\n");
inc_tcp_discards();
- // this packet was normalized elsewhere
- LogTcpEvents(eventcode);
- return retcode | ts_action;
+ return;
}
// update PAWS timestamps
- DebugFormat(DEBUG_STREAM_STATE, "PAWS update tdb->seq %lu > listener->r_win_base %lu\n",
- tdb->seq, listener->r_win_base);
- if (got_ts && SEQ_EQ(listener->r_win_base, tdb->seq))
+ DebugFormat(DEBUG_STREAM_STATE, "PAWS update tsd.seq %lu > listener->r_win_base %lu\n",
+ tsd.get_seq(), listener->r_win_base);
+ if (got_ts && SEQ_EQ(listener->r_win_base, tsd.get_seq()))
{
- if ((int32_t) (tdb->ts - talker->ts_last) >= 0||
- (uint32_t)tdb->pkt->pkth->ts.tv_sec >= talker->ts_last_pkt + PAWS_24DAYS)
+ if ( ( int32_t )( tsd.get_ts() - talker->ts_last ) >= 0 ||
+ (uint32_t)tsd.get_pkt()->pkth->ts.tv_sec >= talker->get_ts_last_packet() + PAWS_24DAYS)
{
DebugMessage(DEBUG_STREAM_STATE, "updating timestamps...\n");
- talker->ts_last = tdb->ts;
- talker->ts_last_pkt = tdb->pkt->pkth->ts.tv_sec;
+ talker->ts_last = tsd.get_ts();
+ talker->set_ts_last_packet(tsd.get_pkt()->pkth->ts.tv_sec);
}
- } else
+ }
+ else
{
DebugMessage(DEBUG_STREAM_STATE, "not updating timestamps...\n");
}
// check for repeat SYNs
- if( !new_ssn && tcph->is_syn_only() )
+ if ( !new_ssn && tcph->is_syn_only() )
{
int action;
- if (!SEQ_EQ(tdb->seq, talker->isn) && listener->normalizer->packet_dropper(tdb, NORM_TCP_BLOCK))
+ if (!SEQ_EQ(tsd.get_seq(), talker->get_iss()) &&
+ listener->normalizer->packet_dropper(tsd, NORM_TCP_BLOCK))
action = ACTION_BAD_PKT;
- else if (talker->s_mgr.state >= TCP_STATE_ESTABLISHED)
- action = listener->normalizer->handle_repeated_syn( tdb );
+ else if (talker->get_tcp_state() >= TcpStreamTracker::TCP_ESTABLISHED)
+ action = listener->normalizer->handle_repeated_syn(tsd);
else
action = ACTION_NOTHING;
if (action != ACTION_NOTHING)
{
/* got a bad SYN on the session, alert! */
- eventcode |= EVENT_SYN_ON_EST;
- LogTcpEvents(eventcode);
- return retcode | action;
+ tel->set_tcp_event(EVENT_SYN_ON_EST);
+ pkt_action_mask |= action;
+ return;
}
}
// Check that the window is within the limits
- if (listener->config->policy != StreamPolicy::OS_PROXY)
+ if (config->policy != StreamPolicy::OS_PROXY)
{
- if (listener->config->max_window && (tdb->win > listener->config->max_window))
+ if (config->max_window && (tsd.get_win() > config->max_window))
{
- DebugMessage(DEBUG_STREAM_STATE, "Got window that was beyond the allowed policy value, bailing\n");
+ DebugMessage(DEBUG_STREAM_STATE,
+ "Got window that was beyond the allowed policy value, bailing\n");
/* got a window too large, alert! */
- eventcode |= EVENT_WINDOW_TOO_LARGE;
+ tel->set_tcp_event(EVENT_WINDOW_TOO_LARGE);
inc_tcp_discards();
- listener->normalizer->packet_dropper(tdb, NORM_TCP_BLOCK);
- LogTcpEvents(eventcode);
- return retcode | ACTION_BAD_PKT;
+ listener->normalizer->packet_dropper(tsd, NORM_TCP_BLOCK);
+ pkt_action_mask |= ACTION_BAD_PKT;
+ return;
}
- else if ((tdb->pkt->packet_flags & PKT_FROM_CLIENT) && (tdb->win <= SLAM_MAX)
- && (tdb->ack == listener->isn + 1)
- && !( tcph->is_fin() | tcph->is_rst() )
- && !(flow->get_session_flags() & SSNFLAG_MIDSTREAM))
+ else if ((tsd.get_pkt()->packet_flags & PKT_FROM_CLIENT) && (tsd.get_win() <= SLAM_MAX)
+ && (tsd.get_ack() == listener->get_iss() + 1)
+ && !( tcph->is_fin() | tcph->is_rst() )
+ && !(flow->get_session_flags() & SSNFLAG_MIDSTREAM))
{
DebugMessage(DEBUG_STREAM_STATE, "Window slammed shut!\n");
/* got a window slam alert! */
- eventcode |= EVENT_WINDOW_SLAM;
+ tel->set_tcp_event(EVENT_WINDOW_SLAM);
inc_tcp_discards();
- if (listener->normalizer->packet_dropper(tdb, NORM_TCP_BLOCK))
+ if (listener->normalizer->packet_dropper(tsd, NORM_TCP_BLOCK))
{
- LogTcpEvents(eventcode);
- return retcode | ACTION_BAD_PKT;
+ pkt_action_mask |= ACTION_BAD_PKT;
+ return;
}
}
}
- if (talker->s_mgr.state_queue != TCP_STATE_NONE)
+ if (talker->s_mgr.state_queue != TcpStreamTracker::TCP_STATE_NONE)
{
- DebugFormat(DEBUG_STREAM_STATE, "Found queued state transition on ack 0x%X, current 0x%X!\n",
- talker->s_mgr.transition_seq, tdb->ack);
+ DebugFormat(DEBUG_STREAM_STATE,
+ "Found queued state transition on ack 0x%X, current 0x%X!\n",
+ talker->s_mgr.transition_seq, tsd.get_ack());
- if (tdb->ack == talker->s_mgr.transition_seq)
+ if (tsd.get_ack() == talker->s_mgr.transition_seq)
{
DebugMessage(DEBUG_STREAM_STATE, "accepting transition!\n");
- talker->s_mgr.state = talker->s_mgr.state_queue;
- talker->s_mgr.state_queue = TCP_STATE_NONE;
+ talker->set_tcp_state(talker->s_mgr.state_queue);
+ talker->s_mgr.state_queue = TcpStreamTracker::TCP_STATE_NONE;
}
}
// process ACK flags
- if( tcph->is_ack() )
+ if ( tcph->is_ack() )
{
DebugMessage(DEBUG_STREAM_STATE, "Got an ACK...\n");
- DebugFormat(DEBUG_STREAM_STATE, " %s [listener] state: %s\n", l, state_names[listener->s_mgr.state]);
+ DebugFormat(DEBUG_STREAM_STATE, " %s [listener] state: %s\n", l,
+ tcp_state_names[listener->get_tcp_state()]);
- switch (listener->s_mgr.state)
+ switch ( listener->get_tcp_state() )
{
- case TCP_STATE_SYN_SENT:
- break;
+ case TcpStreamTracker::TCP_SYN_SENT:
+ break;
- case TCP_STATE_SYN_RCVD:
- DebugMessage(DEBUG_STREAM_STATE, "listener state is SYN_SENT...\n");
- if (IsBetween(listener->l_unackd, listener->l_nxt_seq, tdb->ack))
- {
- UpdateSsn(listener, talker, tdb);
- flow->set_session_flags( SSNFLAG_ESTABLISHED );
- flow->session_state |= STREAM_STATE_ESTABLISHED;
- listener->s_mgr.state = TCP_STATE_ESTABLISHED;
- talker->s_mgr.state = TCP_STATE_ESTABLISHED;
- StreamUpdatePerfBaseState(&sfBase, flow, TCP_STATE_ESTABLISHED);
- /* Indicate this packet completes 3-way handshake */
- tdb->pkt->packet_flags |= PKT_STREAM_TWH;
- }
+ case TcpStreamTracker::TCP_SYN_RECV:
+ DebugMessage(DEBUG_STREAM_STATE, "listener state is SYN_SENT...\n");
+ if ( listener->is_ack_valid(tsd.get_ack() ) )
+ {
+ UpdateSsn(listener, talker, tsd);
+ flow->set_session_flags(SSNFLAG_ESTABLISHED);
+ flow->session_state |= STREAM_STATE_ESTABLISHED;
+ listener->set_tcp_state(TcpStreamTracker::TCP_ESTABLISHED);
+ talker->set_tcp_state(TcpStreamTracker::TCP_ESTABLISHED);
+ update_perf_base_state(&sfBase, TcpStreamTracker::TCP_ESTABLISHED);
+ /* Indicate this packet completes 3-way handshake */
+ tsd.get_pkt()->packet_flags |= PKT_STREAM_TWH;
+ }
- talker->flags |= got_ts;
- if (got_ts && SEQ_EQ(listener->r_nxt_ack, tdb->seq))
- {
- talker->ts_last_pkt = tdb->pkt->pkth->ts.tv_sec;
- talker->ts_last = tdb->ts;
- }
+ talker->flags |= got_ts;
+ if (got_ts && SEQ_EQ(listener->r_nxt_ack, tsd.get_seq()))
+ {
+ talker->set_ts_last_packet(tsd.get_pkt()->pkth->ts.tv_sec);
+ talker->ts_last = tsd.get_ts();
+ }
- break;
+ break;
- case TCP_STATE_ESTABLISHED:
- case TCP_STATE_CLOSE_WAIT:
- UpdateSsn( listener, talker, tdb);
- break;
+ case TcpStreamTracker::TCP_ESTABLISHED:
+ case TcpStreamTracker::TCP_CLOSE_WAIT:
+ UpdateSsn(listener, talker, tsd);
+ break;
- case TCP_STATE_FIN_WAIT_1:
- UpdateSsn(listener, talker, tdb);
+ case TcpStreamTracker::TCP_FIN_WAIT1:
+ UpdateSsn(listener, talker, tsd);
- DebugFormat(DEBUG_STREAM_STATE, "tdb->ack %X >= talker->r_nxt_ack %X\n", tdb->ack, talker->r_nxt_ack);
+ DebugFormat(DEBUG_STREAM_STATE, "tsd.ack %X >= talker->r_nxt_ack %X\n", tsd.get_ack(),
+ talker->r_nxt_ack);
- if (SEQ_EQ(tdb->ack, listener->l_nxt_seq))
+ if ( SEQ_EQ(tsd.get_ack(), listener->get_snd_nxt() ) )
+ {
+ if ((listener->normalizer->get_os_policy() == StreamPolicy::OS_WINDOWS) &&
+ (tsd.get_win() == 0))
{
- if ((listener->normalizer->get_os_policy() == StreamPolicy::OS_WINDOWS) && (tdb->win == 0))
+ tel->set_tcp_event(EVENT_WINDOW_SLAM);
+ inc_tcp_discards();
+
+ if (listener->normalizer->packet_dropper(tsd, NORM_TCP_BLOCK))
{
- eventcode |= EVENT_WINDOW_SLAM;
- inc_tcp_discards();
-
- if (listener->normalizer->packet_dropper(tdb, NORM_TCP_BLOCK))
- {
- LogTcpEvents(eventcode);
- return retcode | ACTION_BAD_PKT;
- }
+ pkt_action_mask |= ACTION_BAD_PKT;
+ return;
}
+ }
- listener->s_mgr.state = TCP_STATE_FIN_WAIT_2;
+ listener->set_tcp_state(TcpStreamTracker::TCP_FIN_WAIT2);
- if( tcph->is_fin() )
+ if ( tcph->is_fin() )
+ {
+ DebugMessage(DEBUG_STREAM_STATE, "seq ok, setting state!\n");
+
+ if ( talker->s_mgr.state_queue == TcpStreamTracker::TCP_STATE_NONE )
{
- DebugMessage(DEBUG_STREAM_STATE, "seq ok, setting state!\n");
-
- if (talker->s_mgr.state_queue == TCP_STATE_NONE)
- {
- talker->s_mgr.state = TCP_STATE_LAST_ACK;
- EndOfFileHandle(tdb->pkt, tcpssn);
- }
- if (flow->get_session_flags() & SSNFLAG_MIDSTREAM)
- {
- // FIXIT-L this should be handled below in fin section
- // but midstream sessions fail the seq test
- listener->s_mgr.state_queue = TCP_STATE_TIME_WAIT;
- listener->s_mgr.transition_seq = tdb->end_seq;
- listener->s_mgr.expected_flags = TH_ACK;
- }
- } else if (listener->s_mgr.state_queue == TCP_STATE_CLOSING)
+ talker->set_tcp_state(TcpStreamTracker::TCP_LAST_ACK);
+ EndOfFileHandle(tsd.get_pkt() );
+ }
+ if ( flow->get_session_flags() & SSNFLAG_MIDSTREAM )
{
- listener->s_mgr.state_queue = TCP_STATE_TIME_WAIT;
- listener->s_mgr.transition_seq = tdb->end_seq;
+ // FIXIT-L this should be handled below in fin section
+ // but midstream sessions fail the seq test
+ listener->s_mgr.state_queue = TcpStreamTracker::TCP_TIME_WAIT;
+ listener->s_mgr.transition_seq = tsd.get_end_seq();
listener->s_mgr.expected_flags = TH_ACK;
}
- } else
- {
- DebugMessage(DEBUG_STREAM_STATE, "bad ack!\n");
}
- break;
-
- case TCP_STATE_FIN_WAIT_2:
- UpdateSsn(listener, talker, tdb);
- if (SEQ_GT(tdb->ack, listener->l_nxt_seq))
+ else if ( listener->s_mgr.state_queue == TcpStreamTracker::TCP_CLOSING )
{
- eventcode |= EVENT_BAD_ACK;
- LogTcpEvents(eventcode);
- listener->normalizer->packet_dropper(tdb, NORM_TCP_BLOCK);
- return retcode | ACTION_BAD_PKT;
+ listener->s_mgr.state_queue = TcpStreamTracker::TCP_TIME_WAIT;
+ listener->s_mgr.transition_seq = tsd.get_end_seq();
+ listener->s_mgr.expected_flags = TH_ACK;
}
- break;
+ }
+ else
+ {
+ DebugMessage(DEBUG_STREAM_STATE, "bad ack!\n");
+ }
+ break;
- case TCP_STATE_CLOSING:
- UpdateSsn(listener, talker, tdb);
- if (SEQ_GEQ(tdb->end_seq, listener->r_nxt_ack))
- listener->s_mgr.state = TCP_STATE_TIME_WAIT;
- break;
+ case TcpStreamTracker::TCP_FIN_WAIT2:
+ UpdateSsn(listener, talker, tsd);
+ if ( SEQ_GT(tsd.get_ack(), listener->get_snd_nxt() ) )
+ {
+ tel->set_tcp_event(EVENT_BAD_ACK);
+ listener->normalizer->packet_dropper(tsd, NORM_TCP_BLOCK);
+ pkt_action_mask |= ACTION_BAD_PKT;
+ return;
+ }
+ break;
- case TCP_STATE_LAST_ACK:
- UpdateSsn( listener, talker, tdb);
+ case TcpStreamTracker::TCP_CLOSING:
+ UpdateSsn(listener, talker, tsd);
+ if (SEQ_GEQ(tsd.get_end_seq(), listener->r_nxt_ack))
+ listener->set_tcp_state(TcpStreamTracker::TCP_TIME_WAIT);
+ break;
- if (SEQ_EQ(tdb->ack, listener->l_nxt_seq))
- listener->s_mgr.state = TCP_STATE_CLOSED;
- break;
+ case TcpStreamTracker::TCP_LAST_ACK:
+ UpdateSsn(listener, talker, tsd);
- default:
- // FIXIT-L safe to ignore when inline?
- break;
+ if ( SEQ_EQ(tsd.get_ack(), listener->get_snd_nxt() ) )
+ listener->set_tcp_state(TcpStreamTracker::TCP_CLOSED);
+ break;
+
+ default:
+ // FIXIT-L safe to ignore when inline?
+ break;
}
- talker->reassembler->flush_on_ack_policy( tdb->pkt );
+ talker->reassembler->flush_on_ack_policy(tsd.get_pkt() );
}
// handle data in the segment
- if (tdb->pkt->dsize)
+ if (tsd.get_pkt()->dsize)
{
DebugFormat(DEBUG_STREAM_STATE, " %s state: %s(%d) getting data\n",
- l, state_names[listener->s_mgr.state], listener->s_mgr.state);
+ l, tcp_state_names[listener->get_tcp_state()], listener->get_tcp_state());
// FIN means only that sender is done talking, other side may continue yapping.
- if ( talker->s_mgr.state == TCP_STATE_FIN_WAIT_2
- or talker->s_mgr.state == TCP_STATE_TIME_WAIT )
+ if ( TcpStreamTracker::TCP_FIN_WAIT2 == talker->get_tcp_state() ||
+ TcpStreamTracker::TCP_TIME_WAIT == talker->get_tcp_state() )
{
// data on a segment when we're not accepting data any more alert!
//EventDataOnClosed(talker->config);
- eventcode |= EVENT_DATA_ON_CLOSED;
- retcode |= ACTION_BAD_PKT;
- listener->normalizer->packet_dropper(tdb, NORM_TCP_BLOCK);
+ tel->set_tcp_event(EVENT_DATA_ON_CLOSED);
+ pkt_action_mask |= ACTION_BAD_PKT;
+ listener->normalizer->packet_dropper(tsd, NORM_TCP_BLOCK);
}
- else if (talker->s_mgr.state == TCP_STATE_CLOSED)
+ else if ( TcpStreamTracker::TCP_CLOSED == talker->get_tcp_state() )
{
// data on a segment when we're not accepting data any more alert!
if (flow->get_session_flags() & SSNFLAG_RESET)
{
//EventDataAfterReset(listener->config);
if (talker->s_mgr.sub_state & SUB_RST_SENT)
- eventcode |= EVENT_DATA_AFTER_RESET;
+ tel->set_tcp_event(EVENT_DATA_AFTER_RESET);
else
- eventcode |= EVENT_DATA_AFTER_RST_RCVD;
+ tel->set_tcp_event(EVENT_DATA_AFTER_RST_RCVD);
}
else
{
//EventDataOnClosed(listener->config);
- eventcode |= EVENT_DATA_ON_CLOSED;
+ tel->set_tcp_event(EVENT_DATA_ON_CLOSED);
}
- retcode |= ACTION_BAD_PKT;
- listener->normalizer->packet_dropper(tdb, NORM_TCP_BLOCK);
+ pkt_action_mask |= ACTION_BAD_PKT;
+ listener->normalizer->packet_dropper(tsd, NORM_TCP_BLOCK);
}
else
{
-
DebugFormat(DEBUG_STREAM_STATE, "Queuing data on listener, t %s, l %s...\n",
- flush_policy_names[talker->flush_policy], flush_policy_names[listener->flush_policy]);
+ flush_policy_names[talker->flush_policy],
+ flush_policy_names[listener->flush_policy]);
if (config->policy != StreamPolicy::OS_PROXY)
{
TcpTracker* st = listener;
// trim to fit in window and mss as needed
- st->normalizer->trim_win_payload(tdb, (st->r_win_base + st->l_window) - st->r_nxt_ack);
+ st->normalizer->trim_win_payload(tsd, ( st->r_win_base + st->get_snd_wnd() -
+ st->r_nxt_ack) );
if (st->mss)
- st->normalizer->trim_mss_payload( tdb, st->mss );
+ st->normalizer->trim_mss_payload(tsd, st->mss);
- st->normalizer->ecn_stripper( tdb->pkt );
+ st->normalizer->ecn_stripper(tsd.get_pkt() );
}
}
// 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 ((tcph->th_flags != 0)
- or (config->policy == StreamPolicy::OS_LINUX)
- or (config->policy == StreamPolicy::OS_PROXY))
+ or (config->policy == StreamPolicy::OS_LINUX)
+ or (config->policy == StreamPolicy::OS_PROXY))
{
- ProcessTcpData( listener, tcpssn, tdb, config);
+ process_tcp_data(listener, tsd);
}
else
{
- eventcode |= EVENT_DATA_WITHOUT_FLAGS;
- listener->normalizer->packet_dropper(tdb, NORM_TCP_BLOCK);
+ tel->set_tcp_event(EVENT_DATA_WITHOUT_FLAGS);
+ listener->normalizer->packet_dropper(tsd, NORM_TCP_BLOCK);
}
}
- listener->reassembler->flush_on_data_policy( tdb->pkt );
+ listener->reassembler->flush_on_data_policy(tsd.get_pkt() );
}
- if( tcph->is_fin() )
+ if ( tcph->is_fin() )
{
DebugMessage(DEBUG_STREAM_STATE, "Got a FIN...\n");
- DebugFormat(DEBUG_STREAM_STATE, " %s state: %s(%d)\n", l, state_names[talker->s_mgr.state], talker->s_mgr.state);
- DebugFormat(DEBUG_STREAM_STATE, "checking ack (0x%X) vs nxt_ack (0x%X)\n", tdb->end_seq, listener->r_win_base);
+ DebugFormat(DEBUG_STREAM_STATE, " %s state: %s(%d)\n", l,
+ tcp_state_names[talker->get_tcp_state()], talker->get_tcp_state());
+ DebugFormat(DEBUG_STREAM_STATE, "checking ack (0x%X) vs nxt_ack (0x%X)\n",
+ tsd.get_end_seq(), listener->r_win_base);
- if (SEQ_LT(tdb->end_seq, listener->r_win_base))
+ if ( SEQ_LT(tsd.get_end_seq(), listener->r_win_base) )
{
DebugMessage(DEBUG_STREAM_STATE, "FIN inside r_win_base, bailing\n");
goto dupfin;
else
{
// need substate since we don't change state immediately
- if ((talker->s_mgr.state >= TCP_STATE_ESTABLISHED) && !(talker->s_mgr.sub_state & SUB_FIN_SENT))
+ if ( (talker->get_tcp_state() >= TcpStreamTracker::TCP_ESTABLISHED )
+ && !( talker->s_mgr.sub_state & SUB_FIN_SENT ) )
{
- talker->l_nxt_seq++;
+ talker->set_snd_nxt(talker->get_snd_nxt() + 1);
//--------------------------------------------------
// FIXIT-L don't bump r_nxt_ack unless FIN is in seq
// because it causes bogus 129:5 cases
// but doing so causes extra gaps
- //if ( SEQ_EQ(tdb->end_seq, listener->r_nxt_ack) )
+ //if ( SEQ_EQ(tsd.end_seq, listener->r_nxt_ack) )
listener->r_nxt_ack++;
//--------------------------------------------------
talker->s_mgr.sub_state |= SUB_FIN_SENT;
- if ((listener->flush_policy != STREAM_FLPOLICY_ON_ACK)
- && (listener->flush_policy != STREAM_FLPOLICY_ON_DATA)
- && listener->normalizer->is_tcp_ips_enabled() )
+ if ( ( listener->flush_policy != STREAM_FLPOLICY_ON_ACK )
+ && ( listener->flush_policy != STREAM_FLPOLICY_ON_DATA )
+ && listener->normalizer->is_tcp_ips_enabled() )
{
- tdb->pkt->packet_flags |= PKT_PDU_TAIL;
+ tsd.get_pkt()->packet_flags |= PKT_PDU_TAIL;
}
}
- switch (talker->s_mgr.state)
+ switch (talker->get_tcp_state())
{
- case TCP_STATE_SYN_RCVD:
- case TCP_STATE_ESTABLISHED:
- if (talker->s_mgr.state_queue == TCP_STATE_CLOSE_WAIT)
- talker->s_mgr.state_queue = TCP_STATE_CLOSING;
+ case TcpStreamTracker::TCP_SYN_RECV:
+ case TcpStreamTracker::TCP_ESTABLISHED:
+ if ( talker->s_mgr.state_queue == TcpStreamTracker::TCP_CLOSE_WAIT )
+ talker->s_mgr.state_queue = TcpStreamTracker::TCP_CLOSING;
- talker->s_mgr.state = TCP_STATE_FIN_WAIT_1;
- EndOfFileHandle(tdb->pkt, tcpssn);
+ talker->set_tcp_state(TcpStreamTracker::TCP_FIN_WAIT1);
+ EndOfFileHandle(tsd.get_pkt() );
- if (!tdb->pkt->dsize)
- listener->reassembler->flush_on_data_policy( tdb->pkt );
+ if ( !tsd.get_pkt()->dsize )
+ listener->reassembler->flush_on_data_policy(tsd.get_pkt() );
- StreamUpdatePerfBaseState(&sfBase, tcpssn->flow, TCP_STATE_CLOSING);
- break;
+ update_perf_base_state(&sfBase, TcpStreamTracker::TCP_CLOSING);
+ break;
- case TCP_STATE_CLOSE_WAIT:
- talker->s_mgr.state = TCP_STATE_LAST_ACK;
- break;
+ case TcpStreamTracker::TCP_CLOSE_WAIT:
+ talker->set_tcp_state(TcpStreamTracker::TCP_LAST_ACK);
+ break;
- case TCP_STATE_FIN_WAIT_1:
- if (!tdb->pkt->dsize)
- tcpssn->retransmit_handle( tdb->pkt );
- break;
+ case TcpStreamTracker::TCP_FIN_WAIT1:
+ if (!tsd.get_pkt()->dsize)
+ retransmit_handle(tsd.get_pkt() );
+ break;
- default:
- /* all other states stay where they are */
- break;
+ default:
+ /* all other states stay where they are */
+ break;
}
- if ((talker->s_mgr.state == TCP_STATE_FIN_WAIT_1) || (talker->s_mgr.state == TCP_STATE_LAST_ACK))
+ if ((talker->get_tcp_state() == TcpStreamTracker::TCP_FIN_WAIT1) ||
+ (talker->get_tcp_state() == TcpStreamTracker::TCP_LAST_ACK))
{
uint32_t end_seq = (flow->get_session_flags() & SSNFLAG_MIDSTREAM)
- ? tdb->end_seq - 1 : tdb->end_seq;
+ ? tsd.get_end_seq() - 1 : tsd.get_end_seq();
- if ((listener->s_mgr.expected_flags == TH_ACK) && SEQ_GEQ(end_seq, listener->s_mgr.transition_seq))
+ if ((listener->s_mgr.expected_flags == TH_ACK) && SEQ_GEQ(end_seq,
+ listener->s_mgr.transition_seq))
{
DebugMessage(DEBUG_STREAM_STATE, "FIN beyond previous, ignoring\n");
- eventcode |= EVENT_BAD_FIN;
- LogTcpEvents(eventcode);
- listener->normalizer->packet_dropper(tdb, NORM_TCP_BLOCK);
- return retcode | ACTION_BAD_PKT;
+ tel->set_tcp_event(EVENT_BAD_FIN);
+ listener->normalizer->packet_dropper(tsd, NORM_TCP_BLOCK);
+ pkt_action_mask |= ACTION_BAD_PKT;
+ return;
}
}
- switch (listener->s_mgr.state)
+ switch ( listener->get_tcp_state() )
{
- case TCP_STATE_ESTABLISHED:
- listener->s_mgr.state_queue = TCP_STATE_CLOSE_WAIT;
- listener->s_mgr.transition_seq = tdb->end_seq + 1;
- listener->s_mgr.expected_flags = TH_ACK;
- break;
+ case TcpStreamTracker::TCP_ESTABLISHED:
+ listener->s_mgr.state_queue = TcpStreamTracker::TCP_CLOSE_WAIT;
+ listener->s_mgr.transition_seq = tsd.get_end_seq() + 1;
+ listener->s_mgr.expected_flags = TH_ACK;
+ break;
- case TCP_STATE_FIN_WAIT_1:
- listener->s_mgr.state_queue = TCP_STATE_CLOSING;
- listener->s_mgr.transition_seq = tdb->end_seq + 1;
- listener->s_mgr.expected_flags = TH_ACK;
- break;
+ case TcpStreamTracker::TCP_FIN_WAIT1:
+ listener->s_mgr.state_queue = TcpStreamTracker::TCP_CLOSING;
+ listener->s_mgr.transition_seq = tsd.get_end_seq() + 1;
+ listener->s_mgr.expected_flags = TH_ACK;
+ break;
- case TCP_STATE_FIN_WAIT_2:
- listener->s_mgr.state_queue = TCP_STATE_TIME_WAIT;
- listener->s_mgr.transition_seq = tdb->end_seq + 1;
- listener->s_mgr.expected_flags = TH_ACK;
- break;
+ case TcpStreamTracker::TCP_FIN_WAIT2:
+ listener->s_mgr.state_queue = TcpStreamTracker::TCP_TIME_WAIT;
+ listener->s_mgr.transition_seq = tsd.get_end_seq() + 1;
+ listener->s_mgr.expected_flags = TH_ACK;
+ break;
+
+ default:
+ // FIXIT - put this here quickly to make compiler happy, what should
+ // be done when not in one of the 3 states above?
+ DebugMessage(DEBUG_STREAM_STATE, "No Action In This State\n");
+ break;
}
}
}
dupfin:
- DebugFormat(DEBUG_STREAM_STATE, " %s [talker] state: %s\n", t, state_names[talker->s_mgr.state]);
- DebugFormat(DEBUG_STREAM_STATE, " %s state: %s(%d)\n", l, state_names[listener->s_mgr.state], listener->s_mgr.state);
+ DebugFormat(DEBUG_STREAM_STATE, " %s [talker] state: %s\n", t,
+ tcp_state_names[talker->get_tcp_state()]);
+ DebugFormat(DEBUG_STREAM_STATE, " %s state: %s(%d)\n", l,
+ tcp_state_names[listener->get_tcp_state()], listener->get_tcp_state());
// handle TIME_WAIT timer stuff
if (!flow->two_way_traffic() &&
- (talker->s_mgr.state >= TCP_STATE_FIN_WAIT_1 || listener->s_mgr.state >= TCP_STATE_FIN_WAIT_1))
+ (talker->get_tcp_state() >= TcpStreamTracker::TCP_FIN_WAIT1 || listener->get_tcp_state() >=
+ TcpStreamTracker::TCP_FIN_WAIT1))
{
if (tcph->is_fin() && tcph->is_ack())
{
- if (talker->s_mgr.state >= TCP_STATE_FIN_WAIT_1)
- talker->s_mgr.state = TCP_STATE_CLOSED;
- if (listener->s_mgr.state >= TCP_STATE_FIN_WAIT_1)
- listener->s_mgr.state = TCP_STATE_CLOSED;
+ if (talker->get_tcp_state() >= TcpStreamTracker::TCP_FIN_WAIT1)
+ talker->set_tcp_state(TcpStreamTracker::TCP_CLOSED);
+
+ if (listener->get_tcp_state() >= TcpStreamTracker::TCP_FIN_WAIT1)
+ listener->set_tcp_state(TcpStreamTracker::TCP_CLOSED);
+
listener->flags |= TF_FORCE_FLUSH;
}
}
- if ( (talker->s_mgr.state == TCP_STATE_TIME_WAIT && listener->s_mgr.state == TCP_STATE_CLOSED)
- || (listener->s_mgr.state == TCP_STATE_TIME_WAIT && talker->s_mgr.state == TCP_STATE_CLOSED)
- || (listener->s_mgr.state == TCP_STATE_TIME_WAIT && talker->s_mgr.state == TCP_STATE_TIME_WAIT)
- || (!flow->two_way_traffic() && (talker->s_mgr.state == TCP_STATE_CLOSED || listener->s_mgr.state == TCP_STATE_CLOSED)))
+ if ( ( talker->get_tcp_state() == TcpStreamTracker::TCP_TIME_WAIT &&
+ listener->get_tcp_state() == TcpStreamTracker::TCP_CLOSED)
+ || (listener->get_tcp_state() == TcpStreamTracker::TCP_TIME_WAIT &&
+ talker->get_tcp_state() == TcpStreamTracker::TCP_CLOSED)
+ || (listener->get_tcp_state() == TcpStreamTracker::TCP_TIME_WAIT &&
+ talker->get_tcp_state() == TcpStreamTracker::TCP_TIME_WAIT)
+ || (!flow->two_way_traffic() && (talker->get_tcp_state() == TcpStreamTracker::TCP_CLOSED ||
+ listener->get_tcp_state() == TcpStreamTracker::TCP_CLOSED)))
{
// The last ACK is a part of the session. Delete the session after processing is complete.
- LogTcpEvents(eventcode);
- TcpSessionCleanup(flow, 0, tdb->pkt);
+ cleanup_session(0, tsd.get_pkt() );
flow->session_state |= STREAM_STATE_CLOSED;
- return retcode | ACTION_LWSSN_CLOSED;
+ pkt_action_mask |= ACTION_LWSSN_CLOSED;
+ return;
}
- else if( listener->s_mgr.state == TCP_STATE_CLOSED
- && talker->s_mgr.state == TCP_STATE_SYN_SENT )
+ else if ( listener->get_tcp_state() == TcpStreamTracker::TCP_CLOSED
+ && talker->get_tcp_state() == TcpStreamTracker::TCP_SYN_SENT )
{
- if( tcph->is_syn_only() )
- flow->set_expire(tdb->pkt, config->session_timeout);
+ if ( tcph->is_syn_only() )
+ flow->set_expire(tsd.get_pkt(), config->session_timeout);
}
-
- LogTcpEvents(eventcode);
- return retcode;
}
-
//-------------------------------------------------------------------------
// TcpSession methods
//-------------------------------------------------------------------------
TcpSession::TcpSession(Flow* flow) :
- Session(flow), ecn(0), event_mask(0)
+ Session(flow), config(nullptr), client(new TcpTracker(true) ),
+ server(new TcpTracker(false) ), ecn(0), ingress_index(0),
+ ingress_group(0), egress_index(0), egress_group(0), daq_flags(0), address_space_id(0),
+ pkt_action_mask(ACTION_NOTHING), require_3whs(true), no_3whs(false)
{
lws_init = tcp_init = false;
+ new_ssn = false;
+
+ tel = new TcpEventLogger;
- memset(&client, 0, sizeof(TcpTracker));
- memset(&server, 0, sizeof(TcpTracker));
+ // initialize stream tracker state machine...
+ new TcpStateNone(tsm, *this);
+ new TcpStateClosed(tsm, *this);
+ new TcpStateListen(tsm, *this);
+ new TcpStateSynSent(tsm, *this);
+ new TcpStateSynRecv(tsm, *this);
+ new TcpStateEstablished(tsm, *this);
+ new TcpStateFinWait1(tsm, *this);
+ new TcpStateFinWait2(tsm, *this);
+ new TcpStateClosing(tsm, *this);
+ new TcpStateCloseWait(tsm, *this);
+ new TcpStateLastAck(tsm, *this);
+ new TcpStateTimeWait(tsm, *this);
}
-TcpSession::~TcpSession()
+TcpSession::~TcpSession(void)
{
if (tcp_init)
- TcpSessionClear(flow, (TcpSession*) flow->session, 1);
-
- delete client.normalizer;
- delete server.normalizer;
- delete client.reassembler;
- delete server.reassembler;
+ {
+ clear_session(1);
+
+ delete client;
+ delete server;
+ }
+
+ delete tel;
}
-void TcpSession::reset()
+void TcpSession::reset(void)
{
if (tcp_init)
- TcpSessionClear(flow, (TcpSession*) flow->session, 2);
+ clear_session(2);
}
bool TcpSession::setup(Packet*)
{
-
- TcpStateHandler* tsh = new TcpStateHandler;
-
// FIXIT-L this it should not be necessary to reset here
reset();
+ client->init_tracker( );
+ server->init_tracker( );
lws_init = tcp_init = false;
- event_mask = 0;
+ no_3whs = false;
+ pkt_action_mask = ACTION_NOTHING;
ecn = 0;
-
- memset(&client, 0, offsetof(TcpTracker, alerts));
- memset(&server, 0, offsetof(TcpTracker, alerts));
-
ingress_index = egress_index = 0;
ingress_group = egress_group = 0;
daq_flags = address_space_id = 0;
- // FIXIT - this is just temp...remove...
- delete tsh;
- tsh = new TcpClosedState;
- delete tsh;
- tsh = new TcpListenState;
- delete tsh;
- tsh = new TcpSynSentState;
- delete tsh;
-
tcpStats.sessions++;
return true;
}
-void TcpSession::cleanup()
+void TcpSession::cleanup(void)
{
// this flushes data and then calls TcpSessionClear()
- TcpSessionCleanup(flow, 1);
+ cleanup_session(1);
}
-void TcpSession::clear()
+void TcpSession::clear(void)
{
- if( tcp_init )
+ if ( tcp_init )
// this does NOT flush data
- TcpSessionClear(flow, this, 1);
+ clear_session(true);
}
void TcpSession::restart(Packet* p)
// sanity check since this is called externally
assert(p->ptrs.tcph);
- TcpTracker* talker, *listener;
+ TcpTracker* talker, * listener;
if (p->packet_flags & PKT_FROM_SERVER)
{
- talker = &server;
- listener = &client;
+ talker = server;
+ listener = client;
}
else
{
- talker = &client;
- listener = &server;
+ talker = client;
+ listener = server;
}
// FIXIT-H on data / on ack must be based on flush policy
if (p->dsize > 0)
- listener->reassembler->flush_on_data_policy( p );
+ listener->reassembler->flush_on_data_policy(p);
if (p->ptrs.tcph->is_ack())
- talker->reassembler->flush_on_ack_policy( p );
+ talker->reassembler->flush_on_ack_policy(p);
}
-void TcpSession::set_splitter(bool c2s, StreamSplitter* ss)
+void TcpSession::print(void)
{
- TcpTracker* trk;
-
- if (c2s)
- trk = &server;
- else
- trk = &client;
-
- if (trk->splitter && tcp_init)
- delete trk->splitter;
-
- trk->splitter = ss;
+ char buf[64];
- if (ss)
- paf_setup(&trk->paf_state);
- else
- trk->flush_policy = STREAM_FLPOLICY_IGNORE;
+ LogMessage("TcpSession:\n");
+ sfip_ntop(&flow->server_ip, buf, sizeof(buf));
+ LogMessage(" server IP: %s\n", buf);
+ sfip_ntop(&flow->client_ip, buf, sizeof(buf));
+ LogMessage(" client IP: %s\n", buf);
+ LogMessage(" server port: %d\n", flow->server_port);
+ LogMessage(" client port: %d\n", flow->client_port);
+ LogMessage(" flags: 0x%X\n", flow->get_session_flags());
+ LogMessage("Client Tracker:\n");
+ client->print();
+ LogMessage("Server Tracker:\n");
+ server->print();
}
-StreamSplitter* TcpSession::get_splitter(bool c2s)
+void TcpSession::set_splitter(bool to_server, StreamSplitter* ss)
{
- if (c2s)
- return server.splitter;
+ TcpTracker* trk = ( to_server ) ? server : client;
- return client.splitter;
+ trk->set_splitter(ss);
}
-void TcpSession::flush_server(Packet *p)
+StreamSplitter* TcpSession::get_splitter(bool to_server)
{
- int flushed;
- TcpTracker *flushTracker = &server;
+ if ( to_server )
+ return server->splitter;
+ else
+ return client->splitter;
+}
- flushTracker->flags |= TF_FORCE_FLUSH;
+void TcpSession::flush_server(Packet* p)
+{
+ server->flags |= TF_FORCE_FLUSH;
- /* If this is a rebuilt packet, don't flush now because we'll
- * overwrite the packet being processed.
- */
- if (p->packet_flags & PKT_REBUILT_STREAM)
+ // 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 */
+ // We'll check & clear the TF_FORCE_FLUSH next time through
return;
}
- /* Need to convert the addresses to network order */
- flushed = flushTracker->reassembler->flush_stream( p, PKT_FROM_SERVER);
+ // Need to convert the addresses to network order
+ if ( server->reassembler->flush_stream(p, PKT_FROM_SERVER) )
+ server->reassembler->purge_flushed_ackd( );
- if (flushed)
- flushTracker->reassembler->purge_flushed_ackd( );
-
- flushTracker->flags &= ~TF_FORCE_FLUSH;
+ server->flags &= ~TF_FORCE_FLUSH;
}
void TcpSession::flush_client(Packet* p)
{
- int flushed;
- TcpTracker *flushTracker = &client;
-
- flushTracker->flags |= TF_FORCE_FLUSH;
+ client->flags |= TF_FORCE_FLUSH;
- /* If this is a rebuilt packet, don't flush now because we'll
- * overwrite the packet being processed.
- */
- if (p->packet_flags & PKT_REBUILT_STREAM)
+ // 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 */
+ // We'll check & clear the TF_FORCE_FLUSH next time through
return;
}
- /* Need to convert the addresses to network order */
- flushed = flushTracker->reassembler->flush_stream(p, PKT_FROM_CLIENT);
-
- if (flushed)
- flushTracker->reassembler->purge_flushed_ackd( );
+ if ( client->reassembler->flush_stream(p, PKT_FROM_CLIENT) )
+ client->reassembler->purge_flushed_ackd( );
- flushTracker->flags &= ~TF_FORCE_FLUSH;
+ client->flags &= ~TF_FORCE_FLUSH;
}
void TcpSession::flush_listener(Packet* p)
{
- TcpTracker *listener = NULL;
+ TcpTracker* listener = nullptr;
uint32_t dir = 0;
- int flushed = 0;
/* figure out direction of this packet -- we should've already
* looked at it, so the packet_flags are already set. */
- if (p->packet_flags & PKT_FROM_SERVER)
+ if ( p->packet_flags & PKT_FROM_SERVER )
{
DebugMessage(DEBUG_STREAM_STATE, "Flushing listener on packet from server\n");
- listener = &client;
+ listener = client;
/* dir of flush is the data from the opposite side */
dir = PKT_FROM_SERVER;
}
- else if (p->packet_flags & PKT_FROM_CLIENT)
+ else if ( p->packet_flags & PKT_FROM_CLIENT )
{
DebugMessage(DEBUG_STREAM_STATE, "Flushing listener on packet from client\n");
- listener = &server;
+ listener = server;
/* dir of flush is the data from the opposite side */
dir = PKT_FROM_CLIENT;
}
- if (dir != 0)
+ if ( dir != 0 )
{
listener->flags |= TF_FORCE_FLUSH;
- flushed = listener->reassembler->flush_stream( p, dir);
-
- if (flushed)
+ if ( listener->reassembler->flush_stream(p, dir) )
listener->reassembler->purge_flushed_ackd( );
listener->flags &= ~TF_FORCE_FLUSH;
void TcpSession::flush_talker(Packet* p)
{
- TcpTracker *talker = NULL;
+ TcpTracker* talker = nullptr;
uint32_t dir = 0;
- int flushed = 0;
/* figure out direction of this packet -- we should've already
* looked at it, so the packet_flags are already set. */
- if (p->packet_flags & PKT_FROM_SERVER)
+ if ( p->packet_flags & PKT_FROM_SERVER )
{
DebugMessage(DEBUG_STREAM_STATE, "Flushing talker on packet from server\n");
- talker = &server;
+ talker = server;
/* dir of flush is the data from the opposite side */
dir = PKT_FROM_CLIENT;
}
- else if (p->packet_flags & PKT_FROM_CLIENT)
+ else if ( p->packet_flags & PKT_FROM_CLIENT )
{
DebugMessage(DEBUG_STREAM_STATE, "Flushing talker on packet from client\n");
- talker = &client;
+ talker = client;
/* dir of flush is the data from the opposite side */
dir = PKT_FROM_SERVER;
}
if (dir != 0)
{
talker->flags |= TF_FORCE_FLUSH;
- flushed = talker->reassembler->flush_stream(p, dir);
-
- if (flushed)
+ if ( talker->reassembler->flush_stream(p, dir) )
talker->reassembler->purge_flushed_ackd( );
talker->flags &= ~TF_FORCE_FLUSH;
// packet / PDU split because PDU rules won't run on raw packets
bool TcpSession::add_alert(Packet* p, uint32_t gid, uint32_t sid)
{
- TcpTracker *st;
+ TcpTracker* st;
StreamAlertInfo* ai;
if (sfip_equals(p->ptrs.ip_api.get_src(), &flow->client_ip))
- st = &server;
+ st = server;
else
- st = &client;
+ st = client;
if (st->alert_count >= MAX_SESSION_ALERTS)
return false;
if (!(p->packet_flags & PKT_REBUILT_STREAM))
return false;
- TcpTracker *st;
+ TcpTracker* st;
if (sfip_equals(p->ptrs.ip_api.get_src(), &flow->client_ip))
- st = &server;
+ st = server;
else
- st = &client;
+ st = client;
for (int i = 0; i < st->alert_count; i++)
{
return false;
}
-int TcpSession::update_alert(Packet *p, uint32_t gid, uint32_t sid,
- uint32_t event_id, uint32_t event_second)
+int TcpSession::update_alert(Packet* p, uint32_t gid, uint32_t sid,
+ uint32_t event_id, uint32_t event_second)
{
- TcpTracker *st;
+ TcpTracker* st;
int i;
uint32_t seq_num;
if (sfip_equals(p->ptrs.ip_api.get_src(), &flow->client_ip))
- st = &server;
+ st = server;
else
- st = &client;
+ st = client;
seq_num = 0;
void TcpSession::set_extra_data(Packet* p, uint32_t xid)
{
- TcpTracker *st;
+ TcpTracker* st;
if (sfip_equals(p->ptrs.ip_api.get_src(), &flow->client_ip))
- st = &server;
+ st = server;
else
- st = &client;
+ st = client;
- st->reassembler->set_xtradata_mask( st->reassembler->get_xtradata_mask() | BIT(xid) );
+ st->reassembler->set_xtradata_mask(st->reassembler->get_xtradata_mask() | BIT(xid) );
}
void TcpSession::clear_extra_data(Packet* p, uint32_t xid)
{
- TcpTracker *st;
+ TcpTracker* st;
if (sfip_equals(p->ptrs.ip_api.get_src(), &flow->client_ip))
- st = &server;
+ st = server;
else
- st = &client;
+ st = client;
if (xid)
- st->reassembler->set_xtradata_mask( st->reassembler->get_xtradata_mask() & ~BIT(xid) );
+ st->reassembler->set_xtradata_mask(st->reassembler->get_xtradata_mask() & ~BIT(xid) );
else
- st->reassembler->set_xtradata_mask( 0 );
+ st->reassembler->set_xtradata_mask(0);
}
-uint8_t TcpSession::get_reassembly_direction()
+uint8_t TcpSession::get_reassembly_direction(void)
{
uint8_t dir = SSN_DIR_NONE;
- if (server.flush_policy != STREAM_FLPOLICY_IGNORE)
+ if (server->flush_policy != STREAM_FLPOLICY_IGNORE)
{
dir |= SSN_DIR_FROM_CLIENT;
}
- if (client.flush_policy != STREAM_FLPOLICY_IGNORE)
+ if (client->flush_policy != STREAM_FLPOLICY_IGNORE)
{
dir |= SSN_DIR_FROM_SERVER;
}
{
if (dir & SSN_DIR_FROM_CLIENT)
{
- if (server.flags & (TF_MISSING_PREV_PKT | TF_MISSING_PKT))
+ if (server->flags & (TF_MISSING_PREV_PKT | TF_MISSING_PKT))
return false;
}
if (dir & SSN_DIR_FROM_SERVER)
{
- if (client.flags & (TF_MISSING_PREV_PKT | TF_MISSING_PKT))
+ if (client->flags & (TF_MISSING_PREV_PKT | TF_MISSING_PKT))
return false;
}
{
if (dir & SSN_DIR_FROM_CLIENT)
{
- if ((server.flags & TF_MISSING_PKT)
- && (server.flags & TF_MISSING_PREV_PKT))
+ if ((server->flags & TF_MISSING_PKT)
+ && (server->flags & TF_MISSING_PREV_PKT))
return SSN_MISSING_BOTH;
- else if (server.flags & TF_MISSING_PREV_PKT)
+ else if (server->flags & TF_MISSING_PREV_PKT)
return SSN_MISSING_BEFORE;
- else if (server.flags & TF_MISSING_PKT)
+ else if (server->flags & TF_MISSING_PKT)
return SSN_MISSING_AFTER;
}
else if (dir & SSN_DIR_FROM_SERVER)
{
- if ((client.flags & TF_MISSING_PKT)
- && (client.flags & TF_MISSING_PREV_PKT))
+ if ((client->flags & TF_MISSING_PKT)
+ && (client->flags & TF_MISSING_PREV_PKT))
return SSN_MISSING_BOTH;
- else if (client.flags & TF_MISSING_PREV_PKT)
+ else if (client->flags & TF_MISSING_PREV_PKT)
return SSN_MISSING_BEFORE;
- else if (client.flags & TF_MISSING_PKT)
+ else if (client->flags & TF_MISSING_PKT)
return SSN_MISSING_AFTER;
}
{
if (dir & SSN_DIR_FROM_CLIENT)
{
- if (server.flags & TF_PKT_MISSED)
+ if (server->flags & TF_PKT_MISSED)
return true;
}
if (dir & SSN_DIR_FROM_SERVER)
{
- if (client.flags & TF_PKT_MISSED)
+ if (client->flags & TF_PKT_MISSED)
return true;
}
{
sfip_t tmpIp;
uint16_t tmpPort;
- TcpTracker tmpTracker;
+ TcpTracker* tracker;
if (sfip_equals(&flow->client_ip, ip) && (flow->client_port == port))
{
}
/* Swap them -- leave flow->ssn_state.direction the same */
-
- /* XXX: Gotta be a more efficient way to do this without the memcpy */
tmpIp = flow->client_ip;
tmpPort = flow->client_port;
flow->client_ip = flow->server_ip;
flow->server_port = tmpPort;
SwapPacketHeaderFoo( );
- memcpy(&tmpTracker, &client, sizeof(TcpTracker));
- memcpy(&client, &server, sizeof(TcpTracker));
- memcpy(&server, &tmpTracker, sizeof(TcpTracker));
+ tracker = client;
+ client = server;
+ server = tracker;
}
-void TcpSession::SetPacketHeaderFoo( const Packet* p )
+void TcpSession::SetPacketHeaderFoo(const Packet* p)
{
if ( daq_flags & DAQ_PKT_FLAG_NOT_FORWARDING )
{
address_space_id = p->pkth->address_space_id;
}
-void TcpSession::GetPacketHeaderFoo( DAQ_PktHdr_t* pkth, uint32_t dir )
+void TcpSession::GetPacketHeaderFoo(DAQ_PktHdr_t* pkth, uint32_t dir)
{
if ( (dir & PKT_FROM_CLIENT) || (daq_flags & DAQ_PKT_FLAG_NOT_FORWARDING) )
{
pkth->address_space_id = address_space_id;
}
-void TcpSession::SwapPacketHeaderFoo( void )
+void TcpSession::SwapPacketHeaderFoo(void)
{
if ( egress_index != DAQ_PKTHDR_UNKNOWN )
{
}
}
-
-
/*
* Main entry point for TCP
*/
{
Profile profile(s5TcpPerfStats);
- TcpDataBlock tdb;
- int status;
-
DEBUG_WRAP(
- char flagbuf[9];
- CreateTCPFlagString(p->ptrs.tcph, flagbuf);
- DebugFormat((DEBUG_STREAM|DEBUG_STREAM_STATE),
- "Got TCP Packet 0x%X:%d -> 0x%X:%d %s\nseq: 0x%X ack:0x%X dsize: %u\n",
- p->ptrs.ip_api.get_src(), p->ptrs.sp, p->ptrs.ip_api.get_dst(), p->ptrs.dp, flagbuf,
- ntohl(p->ptrs.tcph->th_seq), ntohl(p->ptrs.tcph->th_ack), p->dsize);
- );
-
- if (stream.blocked_session(flow, p)
- || (flow->session_state & STREAM_STATE_IGNORE))
+ char flagbuf[9];
+ CreateTCPFlagString(p->ptrs.tcph, flagbuf);
+ DebugFormat((DEBUG_STREAM|DEBUG_STREAM_STATE),
+ "Got TCP Packet 0x%X:%d -> 0x%X:%d %s\nseq: 0x%X ack:0x%X dsize: %u\n",
+ p->ptrs.ip_api.get_src(), p->ptrs.sp, p->ptrs.ip_api.get_dst(), p->ptrs.dp, flagbuf,
+ ntohl(p->ptrs.tcph->th_seq), ntohl(p->ptrs.tcph->th_ack), p->dsize);
+ );
+
+ // FIXIT-L can't get here without protocol being set to TCP, is this really needed??
+ if (flow->protocol != PktType::TCP)
+ {
+ DebugMessage(DEBUG_STREAM_STATE, "Lightweight session not TCP on TCP packet\n");
return ACTION_NOTHING;
+ }
- SetupTcpDataBlock(&tdb, p);
+ if (stream.blocked_session(flow, p) || (flow->session_state & STREAM_STATE_IGNORE))
+ return ACTION_NOTHING;
- StreamTcpConfig* config = get_tcp_cfg(flow->ssn_server);
+ // FIXIT-L expected flow should be checked by flow_con before we get here
+ // harmonize this with that and the checks above
+ char ignore = flow_con->expected_flow(flow, p);
+ if (ignore)
+ {
+ server->flush_policy = STREAM_FLPOLICY_IGNORE;
+ client->flush_policy = STREAM_FLPOLICY_IGNORE;
+ return ACTION_NOTHING;
+ }
+ TcpSegmentDescriptor tsd(flow, p, tel);
if (!lws_init)
{
+ // FIXIT - should only do ths once...
+ if (config == nullptr )
+ {
+ config = get_tcp_cfg(flow->ssn_server);
+ require_3whs = config->require_3whs();
+ client->set_require_3whs(require_3whs);
+ server->set_require_3whs(require_3whs);
+ }
+ set_os_policy( );
+
// FIXIT most of this now looks out of place or redundant
- if (config->require_3whs())
+ if ( require_3whs )
{
if (p->ptrs.tcph->is_syn_only())
{
// Do nothing with this packet since we require a 3-way ;)
DEBUG_WRAP(
- DebugMessage(DEBUG_STREAM_STATE, "Stream: Requiring 3-way Handshake, but failed to retrieve session"
- " object for non SYN packet.\n");
- );
-
- if (!p->ptrs.tcph->is_rst() && !(event_mask & EVENT_NO_3WHS))
+ DebugMessage(DEBUG_STREAM_STATE,
+ "Stream: Requiring 3-way Handshake, but failed to retrieve session"
+ " object for non SYN packet.\n");
+ );
+ if ( !p->ptrs.tcph->is_syn_only() && !p->ptrs.tcph->is_rst() && !no_3whs )
{
- EventNo3whs();
- event_mask |= EVENT_NO_3WHS;
+ tel->EventNo3whs();
+ no_3whs = true;
}
-
#ifdef REG_TEST
- S5TraceTCP(p, flow, &tdb, 1);
+ S5TraceTCP(p, flow, &tsd, 1);
#endif
return 0;
}
{
midstream_pickup_allowed:
if ( !p->ptrs.tcph->is_syn_ack()
- && !p->dsize
- && !(StreamPacketHasWscale(p) & TF_WSCALE) )
+ && !p->dsize
+ && !(tsd.has_wscale() & TF_WSCALE) )
{
#ifdef REG_TEST
- S5TraceTCP(p, flow, &tdb, 1);
+ S5TraceTCP(p, flow, &tsd, 1);
#endif
- return 0;
+ return 0;
}
if (p->ptrs.tcph->is_syn())
}
lws_init = true;
}
- /*
- * Check if the session is expired.
- * Should be done before we do something with the packet...
- * ie, Insert a packet, or handle state change SYN, FIN, RST, etc.
- */
+
+ // 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_session(flow, p))
{
/* Session is timed out */
{
/* If this one has been reset, delete the TCP
* portion, and start a new. */
- TcpSessionCleanup(flow, 1);
+ cleanup_session(1);
}
else
{
DebugMessage(DEBUG_STREAM_STATE, "Stream TCP session timedout!\n");
/* Not reset, simply time'd out. Clean it up */
- TcpSessionCleanup(flow, 1);
+ cleanup_session(1);
}
tcpStats.timeouts++;
}
- status = ProcessTcp(flow, &tdb, config);
+ // FIXIT - need to do something here to handle check for need to swap trackers
+ new_ssn = false;
+ if ( tsm.eval(tsd, *server) )
+ tsm.eval(tsd, *client);
+
+ // FIXIT - this should change once tcp sm fully implemented
+ pkt_action_mask = ACTION_NOTHING;
+ tel->clear_tcp_events();
+
+ if ( tcp_init || tsd.get_pkt()->dsize)
+ process_tcp_packet(tsd);
+ // FIXIT - end
- DebugMessage(DEBUG_STREAM_STATE, "Finished Stream TCP cleanly!\n---------------------------------------------------\n");
+ tel->log_tcp_events();
- if (!(status & ACTION_LWSSN_CLOSED))
+ DebugMessage(DEBUG_STREAM_STATE,
+ "Finished Stream TCP cleanly!\n---------------------------------------------------\n");
+
+ if (!(pkt_action_mask & ACTION_LWSSN_CLOSED))
{
flow->markup_packet_flags(p);
flow->set_expire(p, config->session_timeout);
}
- if (status & ACTION_DISABLE_INSPECTION)
+ if (pkt_action_mask & ACTION_DISABLE_INSPECTION)
{
DisableInspection(p);
- DebugFormat(DEBUG_STREAM_STATE, "Stream Ignoring packet from %d. Session marked as ignore\n",
- p->packet_flags & PKT_FROM_SERVER ? "server" : "client");
+ DebugFormat(DEBUG_STREAM_STATE,
+ "Stream Ignoring packet from %d. Session marked as ignore\n",
+ p->packet_flags & PKT_FROM_SERVER ? "server" : "client");
}
- S5TraceTCP(p, flow, &tdb, 0);
+ S5TraceTCP(p, flow, &tsd, 0);
return 0;
}
-void TcpSession::flush()
+void TcpSession::flush(void)
{
- if( ( server.reassembler->is_segment_pending_flush() ) || (client.reassembler->is_segment_pending_flush() ) )
+ if ( ( server->reassembler->is_segment_pending_flush() ) ||
+ (client->reassembler->is_segment_pending_flush() ) )
{
- server.reassembler->flush_queued_segments( flow, false );
- client.reassembler->flush_queued_segments( flow, false );
+ server->reassembler->flush_queued_segments(flow, false);
+ client->reassembler->flush_queued_segments(flow, false);
}
}
-void TcpSession::start_proxy()
+void TcpSession::start_proxy(void)
{
- client.config->policy = StreamPolicy::OS_PROXY;
- server.config->policy = StreamPolicy::OS_PROXY;
+ config->policy = StreamPolicy::OS_PROXY;
}
//-------------------------------------------------------------------------
tcp_memcap = &mc;
}
-void TcpSession::sinit()
+void TcpSession::sinit(void)
{
s5_pkt = PacketManager::encode_new();
//AtomSplitter::init(); // FIXIT-L PAF implement
}
-void TcpSession::sterm()
+void TcpSession::sterm(void)
{
if (s5_pkt)
{
}
}
-void TcpSession::show(StreamTcpConfig* tcp_config)
-{
- StreamPrintTcpConfig(tcp_config);
-}
-
#include "config.h"
#endif
+#include "perf_monitor/perf_base.h"
#include "detection/detect.h"
#include "flow/session.h"
+#include "stream/libtcp/tcp_state_machine.h"
#include "stream_tcp.h"
-#include "stream/paf.h"
#include "tcp_defs.h"
-
-/* Only track a maximum number of alerts per session */
-#define MAX_SESSION_ALERTS 8
+#include "tcp_stream_config.h"
+#include "tcp_tracker.h"
#ifdef DEBUG
extern const char* const flush_policy_names[];
#endif
-class TcpNormalizer;
-class TcpReassembler;
-
-struct StateMgr
-{
- uint8_t state;
- uint8_t sub_state;
- uint8_t state_queue;
- uint8_t expected_flags;
- uint32_t transition_seq;
- uint32_t stq_get_seq;
-};
-
-//-------------------------------------------------------------------------
-// extra, extra - read all about it!
-// -- u2 is the only output plugin that currently supports extra data
-// -- extra data may be captured before or after alerts
-// -- extra data may be per packet or persistent (saved on session)
-//
-// -- per packet extra data is logged iff we alert on the packet
-// containing the extra data - u2 drives this
-// -- an extra data mask is added to Packet to indicate when per packet
-// extra data is available
-//
-// -- persistent extra data must be logged exactly once for each alert
-// regardless of capture/alert ordering - s5 purge_alerts drives this
-// -- an extra data mask is added to the session trackers to indicate that
-// persistent extra data is available
-//
-// -- event id and second are added to the session alert trackers so that
-// the extra data can be correlated with events
-// -- event id and second are not available when check_alerted()
-// is called; u2 calls StreamUpdateSessionAlertTcp as events are logged
-// to set these fields
-//-------------------------------------------------------------------------
-
-struct StreamAlertInfo
-{
- /* For storing alerts that have already been seen on the session */
- uint32_t sid;
- uint32_t gid;
- uint32_t seq;
- // if we log extra data, event_* is used to correlate with alert
- uint32_t event_id;
- uint32_t event_second;
-};
-
-struct TcpTracker
-{
- StateMgr s_mgr; /* state tracking goodies */
- class StreamSplitter* splitter;
- FlushPolicy flush_policy;
-
- // this is intended to be private to paf but is included
- // directly to avoid the need for allocation; do not directly
- // manipulate within this module.
- PAF_State paf_state; // for tracking protocol aware flushing
-
- StreamTcpConfig* config;
-
- /* Local for these variables means the local part of the connection. For
- * example, if this particular TcpTracker was tracking the client side
- * of a connection, the l_unackd value would represent the client side of
- * the connection's last unacked sequence number
- */
- uint32_t l_unackd; /* local unack'd seq number */
- uint32_t l_nxt_seq; /* local next expected sequence */
- uint32_t l_window; /* local receive window */
-
- uint32_t r_nxt_ack; /* next expected ack from remote side */
- uint32_t r_win_base; /* remote side window base sequence number
- * (i.e. the last ack we got) */
- uint32_t isn; /* initial sequence number */
- uint32_t ts_last; /* last timestamp (for PAWS) */
- uint32_t ts_last_pkt; /* last packet timestamp we got */
-
- TcpNormalizer* normalizer;
- TcpReassembler* reassembler;
- uint32_t small_seg_count;
-
- uint16_t wscale; /* window scale setting */
- uint16_t mss; /* max segment size */
-
- uint8_t mac_addr[6];
- uint8_t flags; /* bitmap flags (TF_xxx) */
-
- uint8_t alert_count; /* number alerts stored (up to MAX_SESSION_ALERTS) */
- StreamAlertInfo alerts[MAX_SESSION_ALERTS]; /* history of alerts */
-};
+class TcpEventLogger;
// FIXIT-L session tracking must be split from reassembly
// into a separate module a la ip_session.cc and ip_defrag.cc
// (of course defrag should also be cleaned up)
-class TcpSession: public Session
+class TcpSession : public Session
{
public:
TcpSession(Flow*);
bool setup(Packet*) override;
int process(Packet*) override;
- void clear() override;
- void cleanup() override;
+ void clear(void) override;
+ void cleanup(void) override;
void restart(Packet*) override;
+ void print(void);
+
+ void set_splitter(bool, StreamSplitter*) override;
+ StreamSplitter* get_splitter(bool) override;
+ void init_new_tcp_session(TcpSegmentDescriptor& tsd);
+ void update_session_state(const tcp::TCPHdr* tcph, TcpSegmentDescriptor& tsd);
void update_direction(char dir, const sfip_t*, uint16_t port) override;
bool add_alert(Packet*, uint32_t gid, uint32_t sid) override;
bool check_alerted(Packet*, uint32_t gid, uint32_t sid) override;
-
int update_alert(Packet*, uint32_t /*gid*/, uint32_t /*sid*/,
- uint32_t /*event_id*/, uint32_t /*event_second*/) override;
+ uint32_t /*event_id*/, uint32_t /*event_second*/) override;
void flush_client(Packet*) override;
void flush_server(Packet*) override;
void flush_talker(Packet*) override;
void flush_listener(Packet*) override;
- void set_splitter(bool /*c2s*/, StreamSplitter*) override;
- StreamSplitter* get_splitter(bool /*c2s*/) override;
void set_extra_data(Packet*, uint32_t /*flag*/) override;
void clear_extra_data(Packet*, uint32_t /*flag*/) override;
bool is_sequenced(uint8_t /*dir*/) override;
bool are_packets_missing(uint8_t /*dir*/) override;
- uint8_t get_reassembly_direction() override;
+ uint8_t get_reassembly_direction(void) override;
uint8_t missing_in_reassembled(uint8_t /*dir*/) override;
- void SetPacketHeaderFoo( const Packet* p );
- void GetPacketHeaderFoo( DAQ_PktHdr_t* pkth, uint32_t dir );
- void SwapPacketHeaderFoo( void );
+ void update_perf_base_state(SFBASE* sf_base, char newState);
+ void SetPacketHeaderFoo(const Packet* p);
+ void GetPacketHeaderFoo(DAQ_PktHdr_t* pkth, uint32_t dir);
+ void SwapPacketHeaderFoo(void);
// FIXIT - these 2 function names convey no meaning afaict... figure out
// why are they called and name appropriately...
- void retransmit_process( Packet* p )
+ void retransmit_process(Packet* p)
{
// Data has already been analyzed so don't bother looking at it again.
- DisableDetect( p );
+ DisableDetect(p);
}
- void retransmit_handle( Packet* p )
+ void retransmit_handle(Packet* p)
{
- flow->call_handlers(p, false);
+ flow->call_handlers(p, false);
}
- void reset();
- void flush();
- void start_proxy();
-
-public:
- TcpTracker client;
- TcpTracker server;
-
+ void reset(void);
+ void flush(void);
+ void start_proxy(void);
static void set_memcap(class Memcap&);
-
- static void sinit();
- static void sterm();
-
- static void show(StreamTcpConfig*);
+ static void sinit(void);
+ static void sterm(void);
+ void update_session_on_server_packet(const tcp::TCPHdr* tcph, TcpSegmentDescriptor& tsd);
+ void update_session_on_client_packet(TcpSegmentDescriptor& tsd);
+ bool handle_syn_on_reset_session(const tcp::TCPHdr* tcph, TcpSegmentDescriptor& tsd);
+ void update_ignored_session(TcpSegmentDescriptor& tsd);
+
+ TcpEventLogger* tel;
+ TcpStreamConfig* config;
+ TcpTracker* client;
+ TcpTracker* server;
+ uint8_t ecn;
+ bool lws_init;
+ bool tcp_init;
int32_t ingress_index; /* Index of the inbound interface. */
- int32_t egress_index; /* Index of the outbound interface. */
int32_t ingress_group; /* Index of the inbound group. */
+ int32_t egress_index; /* Index of the outbound interface. */
int32_t egress_group; /* Index of the outbound group. */
uint32_t daq_flags; /* Flags for the packet (DAQ_PKT_FLAG_*) */
uint16_t address_space_id;
- uint8_t ecn;
- bool lws_init;
- bool tcp_init;
- uint32_t event_mask;
+ uint32_t pkt_action_mask;
+ bool require_3whs;
+ bool no_3whs;
+
+ // FIXIT - deprecate this once tcp state machine is fully implemented
+ bool new_ssn;
private:
+ void EndOfFileHandle(Packet* p);
+ bool flow_exceeds_config_thresholds(TcpTracker* rcv, TcpSegmentDescriptor& tsd);
+ void process_tcp_stream(TcpTracker* rcv, TcpSegmentDescriptor& tsd);
+ int process_tcp_data(TcpTracker* listener, TcpSegmentDescriptor& tsd);
+ void process_tcp_packet(TcpSegmentDescriptor&);
+ void FinishServerInit(TcpSegmentDescriptor& tsd);
+ void swap_trackers(void);
+
+ void NewTcpSessionOnSyn(TcpSegmentDescriptor&);
+ void NewTcpSessionOnSynAck(TcpSegmentDescriptor&);
+ void set_os_policy(void);
+
+ void cleanup_session(int freeApplicationData, Packet* p = nullptr);
+ void clear_session(int freeApplicationData);
+
int process_dis(Packet*);
+ void handle_data_on_syn(const tcp::TCPHdr* tcph, TcpSegmentDescriptor& tsd);
+
+ TcpTracker* talker;
+ TcpTracker* listener;
+ TcpStateMachine tsm;
};
#endif
--- /dev/null
+//--------------------------------------------------------------------------
+// Copyright (C) 2015-2015 Cisco and/or its affiliates. All rights reserved.
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License Version 2 as published
+// by the Free Software Foundation. You may not use, modify or distribute
+// this program under any other version of the GNU General Public License.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+//--------------------------------------------------------------------------
+
+// tcp_state_close_wait.cc author davis mcpherson <davmcphe@cisco.com>
+// Created on: Aug 5, 2015
+
+#include <iostream>
+using namespace std;
+
+#include "tcp_module.h"
+#include "tcp_tracker.h"
+#include "tcp_session.h"
+#include "tcp_normalizer.h"
+#include "tcp_state_close_wait.h"
+
+#ifdef UNIT_TEST
+#include "catch/catch.hpp"
+#endif
+
+TcpStateCloseWait::TcpStateCloseWait(TcpStateMachine& tsm, TcpSession& session) :
+ TcpStateHandler(TcpStreamTracker::TCP_CLOSE_WAIT, tsm), session(session)
+{
+}
+
+TcpStateCloseWait::~TcpStateCloseWait()
+{
+}
+
+bool TcpStateCloseWait::syn_sent(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
+{
+ TcpTracker& trk = static_cast< TcpTracker& >( tracker );
+
+ return default_state_action(tsd, trk, __func__);
+}
+
+bool TcpStateCloseWait::syn_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
+{
+ TcpTracker& trk = static_cast< TcpTracker& >( tracker );
+
+ return default_state_action(tsd, trk, __func__);
+}
+
+bool TcpStateCloseWait::syn_ack_sent(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
+{
+ TcpTracker& trk = static_cast< TcpTracker& >( tracker );
+
+ return default_state_action(tsd, trk, __func__);
+}
+
+bool TcpStateCloseWait::syn_ack_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
+{
+ TcpTracker& trk = static_cast< TcpTracker& >( tracker );
+
+ return default_state_action(tsd, trk, __func__);
+}
+
+bool TcpStateCloseWait::ack_sent(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
+{
+ TcpTracker& trk = static_cast< TcpTracker& >( tracker );
+
+ return default_state_action(tsd, trk, __func__);
+}
+
+bool TcpStateCloseWait::ack_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
+{
+ TcpTracker& trk = static_cast< TcpTracker& >( tracker );
+
+ return default_state_action(tsd, trk, __func__);
+}
+
+bool TcpStateCloseWait::data_seg_sent(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
+{
+ TcpTracker& trk = static_cast< TcpTracker& >( tracker );
+
+ return default_state_action(tsd, trk, __func__);
+}
+
+bool TcpStateCloseWait::data_seg_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
+{
+ TcpTracker& trk = static_cast< TcpTracker& >( tracker );
+
+ return default_state_action(tsd, trk, __func__);
+}
+
+bool TcpStateCloseWait::fin_sent(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
+{
+ TcpTracker& trk = static_cast< TcpTracker& >( tracker );
+
+ return default_state_action(tsd, trk, __func__);
+}
+
+bool TcpStateCloseWait::fin_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
+{
+ TcpTracker& trk = static_cast< TcpTracker& >( tracker );
+
+ return default_state_action(tsd, trk, __func__);
+}
+
+bool TcpStateCloseWait::rst_sent(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
+{
+ TcpTracker& trk = static_cast< TcpTracker& >( tracker );
+
+ return default_state_action(tsd, trk, __func__);
+}
+
+bool TcpStateCloseWait::rst_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
+{
+ TcpTracker& trk = static_cast< TcpTracker& >( tracker );
+
+ return default_state_action(tsd, trk, __func__);
+}
+
--- /dev/null
+//--------------------------------------------------------------------------
+// Copyright (C) 2015-2015 Cisco and/or its affiliates. All rights reserved.
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License Version 2 as published
+// by the Free Software Foundation. You may not use, modify or distribute
+// this program under any other version of the GNU General Public License.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+//--------------------------------------------------------------------------
+
+// tcp_state_close_wait.h author davis mcpherson <davmcphe@@cisco.com>
+// Created on: Aug 5, 2015
+
+#ifndef TCP_STATE_CLOSE_WAIT_H
+#define TCP_STATE_CLOSE_WAIT_H
+
+#include "stream/libtcp/tcp_state_handler.h"
+
+class TcpSession;
+
+class TcpStateCloseWait : public TcpStateHandler
+{
+public:
+ TcpStateCloseWait(TcpStateMachine&, TcpSession&);
+ virtual ~TcpStateCloseWait(void);
+
+ bool syn_sent(TcpSegmentDescriptor&, TcpStreamTracker&) override;
+ bool syn_recv(TcpSegmentDescriptor&, TcpStreamTracker&) override;
+ bool syn_ack_sent(TcpSegmentDescriptor&, TcpStreamTracker&) override;
+ bool syn_ack_recv(TcpSegmentDescriptor&, TcpStreamTracker&) override;
+ bool ack_sent(TcpSegmentDescriptor&, TcpStreamTracker&) override;
+ bool ack_recv(TcpSegmentDescriptor&, TcpStreamTracker&) override;
+ bool data_seg_sent(TcpSegmentDescriptor&, TcpStreamTracker&) override;
+ bool data_seg_recv(TcpSegmentDescriptor&, TcpStreamTracker&) override;
+ bool fin_sent(TcpSegmentDescriptor&, TcpStreamTracker&) override;
+ bool fin_recv(TcpSegmentDescriptor&, TcpStreamTracker&) override;
+ bool rst_sent(TcpSegmentDescriptor&, TcpStreamTracker&) override;
+ bool rst_recv(TcpSegmentDescriptor&, TcpStreamTracker&) override;
+
+private:
+ TcpSession& session;
+};
+
+#endif
+
--- /dev/null
+//--------------------------------------------------------------------------
+// Copyright (C) 2015-2015 Cisco and/or its affiliates. All rights reserved.
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License Version 2 as published
+// by the Free Software Foundation. You may not use, modify or distribute
+// this program under any other version of the GNU General Public License.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+//--------------------------------------------------------------------------
+
+// tcp_state_closed.cc author davis mcpherson <davmcphe@@cisco.com>
+// Created on: Jul 30, 2015
+
+#include "stream/stream.h"
+
+#include "tcp_module.h"
+#include "tcp_tracker.h"
+#include "tcp_session.h"
+#include "tcp_state_closed.h"
+
+#ifdef UNIT_TEST
+#include "catch/catch.hpp"
+#include "stream/libtcp/stream_tcp_unit_test.h"
+#endif
+
+TcpStateClosed::TcpStateClosed(TcpStateMachine& tsm, TcpSession& session) :
+ TcpStateHandler(TcpStreamTracker::TCP_CLOSED, tsm), session(session)
+{
+}
+
+TcpStateClosed::~TcpStateClosed()
+{
+}
+
+bool TcpStateClosed::syn_sent(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
+{
+ TcpTracker& trk = static_cast< TcpTracker& >( tracker );
+
+ return default_state_action(tsd, tracker, __func__);
+}
+
+bool TcpStateClosed::syn_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
+{
+ TcpTracker& trk = static_cast< TcpTracker& >( tracker );
+
+ return default_state_action(tsd, tracker, __func__);
+}
+
+bool TcpStateClosed::syn_ack_sent(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
+{
+ TcpTracker& trk = static_cast< TcpTracker& >( tracker );
+
+ return default_state_action(tsd, tracker, __func__);
+}
+
+bool TcpStateClosed::syn_ack_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
+{
+ TcpTracker& trk = static_cast< TcpTracker& >( tracker );
+
+ return default_state_action(tsd, tracker, __func__);
+}
+
+bool TcpStateClosed::ack_sent(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
+{
+ TcpTracker& trk = static_cast< TcpTracker& >( tracker );
+
+ return default_state_action(tsd, tracker, __func__);
+}
+
+bool TcpStateClosed::ack_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
+{
+ TcpTracker& trk = static_cast< TcpTracker& >( tracker );
+
+ return default_state_action(tsd, tracker, __func__);
+}
+
+bool TcpStateClosed::data_seg_sent(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
+{
+ TcpTracker& trk = static_cast< TcpTracker& >( tracker );
+
+ return default_state_action(tsd, tracker, __func__);
+}
+
+bool TcpStateClosed::data_seg_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
+{
+ TcpTracker& trk = static_cast< TcpTracker& >( tracker );
+
+ return default_state_action(tsd, tracker, __func__);
+}
+
+bool TcpStateClosed::fin_sent(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
+{
+ TcpTracker& trk = static_cast< TcpTracker& >( tracker );
+
+ return default_state_action(tsd, tracker, __func__);
+}
+
+bool TcpStateClosed::fin_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
+{
+ TcpTracker& trk = static_cast< TcpTracker& >( tracker );
+
+ return default_state_action(tsd, tracker, __func__);
+}
+
+bool TcpStateClosed::rst_sent(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
+{
+ TcpTracker& trk = static_cast< TcpTracker& >( tracker );
+
+ return default_state_action(tsd, tracker, __func__);
+}
+
+bool TcpStateClosed::rst_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
+{
+ TcpTracker& trk = static_cast< TcpTracker& >( tracker );
+
+ return default_state_action(tsd, tracker, __func__);
+}
+
+#ifdef FOO // FIXIT - UNIT_TEST need work!!
+#include "tcp_normalizers.h"
+#include "tcp_reassemblers.h"
+
+TEST_CASE("TCP State Closed", "[tcp_closed_state][stream_tcp]")
+{
+ // initialization code here
+ Flow* flow = new Flow;
+ TcpTracker* ctrk = new TcpTracker(true);
+ TcpTracker* strk = new TcpTracker(false);
+ TcpEventLogger* tel = new TcpEventLogger;
+ TcpSession* session = new TcpSession(flow);
+ TcpStateMachine* tsm = new TcpStateMachine;
+ TcpStateHandler* tsh = new TcpStateClosed(*tsm, *session);
+ ctrk->normalizer = TcpNormalizerFactory::create(session, StreamPolicy::OS_LINUX, ctrk, strk);
+ strk->normalizer = TcpNormalizerFactory::create(session, StreamPolicy::OS_LINUX, strk, ctrk);
+ ctrk->reassembler = TcpReassemblerFactory::create(session, ctrk, StreamPolicy::OS_LINUX,
+ false);
+ strk->reassembler = TcpReassemblerFactory::create(session, strk, StreamPolicy::OS_LINUX, true);
+
+ SECTION("syn_packet")
+ {
+ Packet* pkt = get_syn_packet(flow);
+ REQUIRE( ( pkt != nullptr ) );
+
+ SECTION("syn_sent")
+ {
+ flow->ssn_state.direction = FROM_CLIENT;
+ TcpSegmentDescriptor tsd(flow, pkt, tel);
+ ctrk->set_tcp_event(tsd);
+ ctrk->set_require_3whs(false);
+ tsh->eval(tsd, *ctrk);
+ CHECK(TcpStreamTracker::TCP_SYN_SENT_EVENT == ctrk->get_tcp_event() );
+ //CHECK( ( ctrk->get_iss() == 9050 ) );
+ //CHECK( ( ctrk->get_snd_una() == 9051 ) );
+ //CHECK( ( ctrk->get_snd_nxt() == 9050 ) );
+ //CHECK( ( ctrk->get_snd_wnd() == 8192 ) );
+ }
+
+ SECTION("syn_recv")
+ {
+ flow->ssn_state.direction = FROM_SERVER;
+ TcpSegmentDescriptor tsd(flow, pkt, tel);
+ ctrk->set_tcp_event(tsd);
+ tsh->eval(tsd, *ctrk);
+ CHECK( ( tsh->get_tcp_event() == ctrk->get_tcp_event() ) );
+ }
+
+ delete pkt;
+ }
+
+ SECTION("syn_ack_packet")
+ {
+ Packet* pkt = get_syn_ack_packet(flow);
+ REQUIRE( ( pkt != nullptr ) );
+
+ SECTION("syn_ack_sent")
+ {
+ flow->ssn_state.direction = FROM_CLIENT;
+ TcpSegmentDescriptor tsd(flow, pkt, tel);
+ ctrk->set_tcp_event(tsd);
+ ctrk->set_require_3whs(false);
+ tsh->eval(tsd, *ctrk);
+ CHECK( ( tsh->get_tcp_event() == ctrk->get_tcp_event() ) );
+ }
+
+ SECTION("syn_ack_recv")
+ {
+ flow->ssn_state.direction = FROM_SERVER;
+ TcpSegmentDescriptor tsd(flow, pkt, tel);
+ ctrk->set_tcp_event(tsd);
+ ctrk->set_require_3whs(false);
+ tsh->eval(tsd, *ctrk);
+ CHECK( ( tsh->get_tcp_event() == ctrk->get_tcp_event() ) );
+ }
+
+ delete pkt;
+ }
+
+ SECTION("ack_packet")
+ {
+ Packet* pkt = get_ack_packet(flow);
+ REQUIRE( ( pkt != nullptr ) );
+
+ SECTION("ack_sent")
+ {
+ flow->ssn_state.direction = FROM_CLIENT;
+ TcpSegmentDescriptor tsd(flow, pkt, tel);
+ ctrk->set_tcp_event(tsd);
+ ctrk->set_require_3whs(false);
+ tsh->eval(tsd, *ctrk);
+ CHECK( ( tsh->get_tcp_event() == ctrk->get_tcp_event() ) );
+ }
+
+ SECTION("ack_recv")
+ {
+ flow->ssn_state.direction = FROM_SERVER;
+ TcpSegmentDescriptor tsd(flow, pkt, tel);
+ ctrk->set_tcp_event(tsd);
+ ctrk->set_require_3whs(false);
+ tsh->eval(tsd, *ctrk);
+ CHECK( ( tsh->get_tcp_event() == ctrk->get_tcp_event() ) );
+ }
+
+ delete pkt;
+ }
+
+ SECTION("data_seg_packet")
+ {
+ Packet* pkt = get_data_packet(flow);
+ REQUIRE( ( pkt != nullptr ) );
+
+ SECTION("data_seg_sent")
+ {
+ flow->ssn_state.direction = FROM_CLIENT;
+ TcpSegmentDescriptor tsd(flow, pkt, tel);
+ ctrk->set_tcp_event(tsd);
+ ctrk->set_require_3whs(false);
+ tsh->eval(tsd, *ctrk);
+ CHECK( ( tsh->get_tcp_event() == ctrk->get_tcp_event() ) );
+ }
+
+ SECTION("data_seg_recv")
+ {
+ flow->ssn_state.direction = FROM_SERVER;
+ TcpSegmentDescriptor tsd(flow, pkt, tel);
+ ctrk->set_tcp_event(tsd);
+ ctrk->set_require_3whs(false);
+ tsh->eval(tsd, *ctrk);
+ CHECK( ( tsh->get_tcp_event() == ctrk->get_tcp_event() ) );
+ }
+
+ delete pkt;
+ }
+
+ SECTION("fin_packet")
+ {
+ Packet* pkt = get_fin_packet(flow);
+ REQUIRE( ( pkt != nullptr ) );
+
+ SECTION("fin_sent")
+ {
+ flow->ssn_state.direction = FROM_CLIENT;
+ TcpSegmentDescriptor tsd(flow, pkt, tel);
+ ctrk->set_tcp_event(tsd);
+ ctrk->set_require_3whs(false);
+ tsh->eval(tsd, *ctrk);
+ CHECK( ( tsh->get_tcp_event() == ctrk->get_tcp_event() ) );
+ }
+
+ SECTION("fin_recv")
+ {
+ flow->ssn_state.direction = FROM_SERVER;
+ TcpSegmentDescriptor tsd(flow, pkt, tel);
+ ctrk->set_tcp_event(tsd);
+ ctrk->set_require_3whs(false);
+ tsh->eval(tsd, *ctrk);
+ CHECK( ( tsh->get_tcp_event() == ctrk->get_tcp_event() ) );
+ }
+
+ delete pkt;
+ }
+
+ SECTION("rst_packet")
+ {
+ Packet* pkt = get_rst_packet(flow);
+ REQUIRE( ( pkt != nullptr ));
+
+ SECTION("rst_sent")
+ {
+ flow->ssn_state.direction = FROM_CLIENT;
+ TcpSegmentDescriptor tsd(flow, pkt, tel);
+ ctrk->set_tcp_event(tsd);
+ ctrk->set_require_3whs(false);
+ tsh->eval(tsd, *ctrk);
+ CHECK( ( tsh->get_tcp_event() == ctrk->get_tcp_event() ));
+ }
+
+ SECTION("rst_recv")
+ {
+ flow->ssn_state.direction = FROM_SERVER;
+ TcpSegmentDescriptor tsd(flow, pkt, tel);
+ ctrk->set_tcp_event(tsd);
+ ctrk->set_require_3whs(false);
+ tsh->eval(tsd, *ctrk);
+ CHECK( ( tsh->get_tcp_event() == ctrk->get_tcp_event() ) );
+ }
+
+ delete pkt;
+ }
+
+ delete flow;
+ delete tsh;
+ delete ctrk;
+ delete strk;
+}
+
+#endif
+
--- /dev/null
+//--------------------------------------------------------------------------
+// Copyright (C) 2015-2015 Cisco and/or its affiliates. All rights reserved.
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License Version 2 as published
+// by the Free Software Foundation. You may not use, modify or distribute
+// this program under any other version of the GNU General Public License.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+//--------------------------------------------------------------------------
+
+// tcp_state_closed.h author davis mcpherson <davmcphe@cisco.com>
+// Created on: Jul 30, 2015
+
+#ifndef TCP_STATE_CLOSED_H
+#define TCP_STATE_CLOSED_H
+
+#include "stream/libtcp/tcp_state_handler.h"
+
+class TcpSession;
+
+class TcpStateClosed : public TcpStateHandler
+{
+public:
+ TcpStateClosed(TcpStateMachine&, TcpSession&);
+ virtual ~TcpStateClosed(void);
+
+ bool syn_sent(TcpSegmentDescriptor&, TcpStreamTracker&) override;
+ bool syn_recv(TcpSegmentDescriptor&, TcpStreamTracker&) override;
+ bool syn_ack_sent(TcpSegmentDescriptor&, TcpStreamTracker&) override;
+ bool syn_ack_recv(TcpSegmentDescriptor&, TcpStreamTracker&) override;
+ bool ack_sent(TcpSegmentDescriptor&, TcpStreamTracker&) override;
+ bool ack_recv(TcpSegmentDescriptor&, TcpStreamTracker&) override;
+ bool data_seg_sent(TcpSegmentDescriptor&, TcpStreamTracker&) override;
+ bool data_seg_recv(TcpSegmentDescriptor&, TcpStreamTracker&) override;
+ bool fin_sent(TcpSegmentDescriptor&, TcpStreamTracker&) override;
+ bool fin_recv(TcpSegmentDescriptor&, TcpStreamTracker&) override;
+ bool rst_sent(TcpSegmentDescriptor&, TcpStreamTracker&) override;
+ bool rst_recv(TcpSegmentDescriptor&, TcpStreamTracker&) override;
+
+private:
+ TcpSession& session;
+};
+
+#endif
+
--- /dev/null
+//--------------------------------------------------------------------------
+// Copyright (C) 2015-2015 Cisco and/or its affiliates. All rights reserved.
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License Version 2 as published
+// by the Free Software Foundation. You may not use, modify or distribute
+// this program under any other version of the GNU General Public License.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+//--------------------------------------------------------------------------
+
+// tcp_state_closing.cc author davis mcpherson <davmcphe@cisco.com>
+// Created on: Aug 5, 2015
+
+#include <iostream>
+using namespace std;
+
+#include "tcp_module.h"
+#include "tcp_tracker.h"
+#include "tcp_session.h"
+#include "tcp_normalizer.h"
+#include "tcp_state_closing.h"
+
+#ifdef UNIT_TEST
+#include "catch/catch.hpp"
+#endif
+
+TcpStateClosing::TcpStateClosing(TcpStateMachine& tsm, TcpSession& session) :
+ TcpStateHandler(TcpStreamTracker::TCP_CLOSING, tsm), session(session)
+{
+}
+
+TcpStateClosing::~TcpStateClosing()
+{
+}
+
+bool TcpStateClosing::syn_sent(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
+{
+ TcpTracker& trk = static_cast< TcpTracker& >( tracker );
+
+ return default_state_action(tsd, trk, __func__);
+}
+
+bool TcpStateClosing::syn_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
+{
+ TcpTracker& trk = static_cast< TcpTracker& >( tracker );
+
+ return default_state_action(tsd, trk, __func__);
+}
+
+bool TcpStateClosing::syn_ack_sent(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
+{
+ TcpTracker& trk = static_cast< TcpTracker& >( tracker );
+
+ return default_state_action(tsd, trk, __func__);
+}
+
+bool TcpStateClosing::syn_ack_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
+{
+ TcpTracker& trk = static_cast< TcpTracker& >( tracker );
+
+ return default_state_action(tsd, trk, __func__);
+}
+
+bool TcpStateClosing::ack_sent(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
+{
+ TcpTracker& trk = static_cast< TcpTracker& >( tracker );
+
+ return default_state_action(tsd, trk, __func__);
+}
+
+bool TcpStateClosing::ack_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
+{
+ TcpTracker& trk = static_cast< TcpTracker& >( tracker );
+
+ return default_state_action(tsd, trk, __func__);
+}
+
+bool TcpStateClosing::data_seg_sent(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
+{
+ TcpTracker& trk = static_cast< TcpTracker& >( tracker );
+
+ return default_state_action(tsd, trk, __func__);
+}
+
+bool TcpStateClosing::data_seg_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
+{
+ TcpTracker& trk = static_cast< TcpTracker& >( tracker );
+
+ return default_state_action(tsd, trk, __func__);
+}
+
+bool TcpStateClosing::fin_sent(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
+{
+ TcpTracker& trk = static_cast< TcpTracker& >( tracker );
+
+ return default_state_action(tsd, trk, __func__);
+}
+
+bool TcpStateClosing::fin_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
+{
+ TcpTracker& trk = static_cast< TcpTracker& >( tracker );
+
+ return default_state_action(tsd, trk, __func__);
+}
+
+bool TcpStateClosing::rst_sent(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
+{
+ TcpTracker& trk = static_cast< TcpTracker& >( tracker );
+
+ return default_state_action(tsd, trk, __func__);
+}
+
+bool TcpStateClosing::rst_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
+{
+ TcpTracker& trk = static_cast< TcpTracker& >( tracker );
+
+ return default_state_action(tsd, trk, __func__);
+}
+
--- /dev/null
+//--------------------------------------------------------------------------
+// Copyright (C) 2015-2015 Cisco and/or its affiliates. All rights reserved.
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License Version 2 as published
+// by the Free Software Foundation. You may not use, modify or distribute
+// this program under any other version of the GNU General Public License.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+//--------------------------------------------------------------------------
+
+// tcp_state_closing.h author davis mcpherson <davmcphe@cisco.com>
+// Created on: Aug 5, 2015
+
+#ifndef TCP_STATE_CLOSING_H
+#define TCP_STATE_CLOSING_H
+
+#include "stream/libtcp/tcp_state_handler.h"
+
+class TcpSession;
+
+class TcpStateClosing : public TcpStateHandler
+{
+public:
+ TcpStateClosing(TcpStateMachine&, TcpSession&);
+ virtual ~TcpStateClosing(void);
+
+ bool syn_sent(TcpSegmentDescriptor&, TcpStreamTracker&) override;
+ bool syn_recv(TcpSegmentDescriptor&, TcpStreamTracker&) override;
+ bool syn_ack_sent(TcpSegmentDescriptor&, TcpStreamTracker&) override;
+ bool syn_ack_recv(TcpSegmentDescriptor&, TcpStreamTracker&) override;
+ bool ack_sent(TcpSegmentDescriptor&, TcpStreamTracker&) override;
+ bool ack_recv(TcpSegmentDescriptor&, TcpStreamTracker&) override;
+ bool data_seg_sent(TcpSegmentDescriptor&, TcpStreamTracker&) override;
+ bool data_seg_recv(TcpSegmentDescriptor&, TcpStreamTracker&) override;
+ bool fin_sent(TcpSegmentDescriptor&, TcpStreamTracker&) override;
+ bool fin_recv(TcpSegmentDescriptor&, TcpStreamTracker&) override;
+ bool rst_sent(TcpSegmentDescriptor&, TcpStreamTracker&) override;
+ bool rst_recv(TcpSegmentDescriptor&, TcpStreamTracker&) override;
+
+private:
+ TcpSession& session;
+};
+
+#endif
+
--- /dev/null
+//--------------------------------------------------------------------------
+// Copyright (C) 2015-2015 Cisco and/or its affiliates. All rights reserved.
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License Version 2 as published
+// by the Free Software Foundation. You may not use, modify or distribute
+// this program under any other version of the GNU General Public License.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+//--------------------------------------------------------------------------
+
+// tcp_state_established.cc author davis mcpherson <davmcphe@@cisco.com>
+// Created on: Jul 30, 2015
+
+#include "tcp_module.h"
+#include "tcp_tracker.h"
+#include "tcp_session.h"
+#include "tcp_normalizer.h"
+#include "tcp_state_established.h"
+
+TcpStateEstablished::TcpStateEstablished(TcpStateMachine& tsm, TcpSession& session) :
+ TcpStateHandler(TcpStreamTracker::TCP_ESTABLISHED, tsm), session(session)
+{
+}
+
+TcpStateEstablished::~TcpStateEstablished()
+{
+}
+
+bool TcpStateEstablished::syn_sent(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
+{
+ TcpTracker& trk = static_cast< TcpTracker& >( tracker );
+
+ return default_state_action(tsd, trk, __func__);
+}
+
+bool TcpStateEstablished::syn_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
+{
+ TcpTracker& trk = static_cast< TcpTracker& >( tracker );
+
+ return default_state_action(tsd, trk, __func__);
+}
+
+bool TcpStateEstablished::syn_ack_sent(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
+{
+ TcpTracker& trk = static_cast< TcpTracker& >( tracker );
+
+ return default_state_action(tsd, trk, __func__);
+}
+
+bool TcpStateEstablished::syn_ack_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
+{
+ TcpTracker& trk = static_cast< TcpTracker& >( tracker );
+
+ return default_state_action(tsd, trk, __func__);
+}
+
+bool TcpStateEstablished::ack_sent(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
+{
+ TcpTracker& trk = static_cast< TcpTracker& >( tracker );
+
+ return default_state_action(tsd, trk, __func__);
+}
+
+bool TcpStateEstablished::ack_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
+{
+ TcpTracker& trk = static_cast< TcpTracker& >( tracker );
+
+ return default_state_action(tsd, trk, __func__);
+}
+
+bool TcpStateEstablished::data_seg_sent(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
+{
+ TcpTracker& trk = static_cast< TcpTracker& >( tracker );
+
+ return default_state_action(tsd, trk, __func__);
+}
+
+bool TcpStateEstablished::data_seg_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
+{
+ TcpTracker& trk = static_cast< TcpTracker& >( tracker );
+
+ return default_state_action(tsd, trk, __func__);
+}
+
+bool TcpStateEstablished::fin_sent(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
+{
+ TcpTracker& trk = static_cast< TcpTracker& >( tracker );
+
+ return default_state_action(tsd, trk, __func__);
+}
+
+bool TcpStateEstablished::fin_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
+{
+ TcpTracker& trk = static_cast< TcpTracker& >( tracker );
+
+ return default_state_action(tsd, trk, __func__);
+}
+
+bool TcpStateEstablished::rst_sent(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
+{
+ TcpTracker& trk = static_cast< TcpTracker& >( tracker );
+
+ return default_state_action(tsd, trk, __func__);
+}
+
+bool TcpStateEstablished::rst_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
+{
+ TcpTracker& trk = static_cast< TcpTracker& >( tracker );
+
+ return default_state_action(tsd, trk, __func__);
+}
+
--- /dev/null
+//--------------------------------------------------------------------------
+// Copyright (C) 2015-2015 Cisco and/or its affiliates. All rights reserved.
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License Version 2 as published
+// by the Free Software Foundation. You may not use, modify or distribute
+// this program under any other version of the GNU General Public License.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+//--------------------------------------------------------------------------
+
+// tcp_state_established.h author davis mcpherson <davmcphe@cisco.com>
+// Created on: Jul 30, 2015
+
+#ifndef TCP_STATE_ESTABLISHED_H
+#define TCP_STATE_ESTABLISHED_H
+
+#include "stream/libtcp/tcp_state_handler.h"
+
+class TcpSession;
+
+class TcpStateEstablished : public TcpStateHandler
+{
+public:
+ TcpStateEstablished(TcpStateMachine&, TcpSession&);
+ virtual ~TcpStateEstablished(void);
+
+ bool syn_sent(TcpSegmentDescriptor&, TcpStreamTracker&) override;
+ bool syn_recv(TcpSegmentDescriptor&, TcpStreamTracker&) override;
+ bool syn_ack_sent(TcpSegmentDescriptor&, TcpStreamTracker&) override;
+ bool syn_ack_recv(TcpSegmentDescriptor&, TcpStreamTracker&) override;
+ bool ack_sent(TcpSegmentDescriptor&, TcpStreamTracker&) override;
+ bool ack_recv(TcpSegmentDescriptor&, TcpStreamTracker&) override;
+ bool data_seg_sent(TcpSegmentDescriptor&, TcpStreamTracker&) override;
+ bool data_seg_recv(TcpSegmentDescriptor&, TcpStreamTracker&) override;
+ bool fin_sent(TcpSegmentDescriptor&, TcpStreamTracker&) override;
+ bool fin_recv(TcpSegmentDescriptor&, TcpStreamTracker&) override;
+ bool rst_sent(TcpSegmentDescriptor&, TcpStreamTracker&) override;
+ bool rst_recv(TcpSegmentDescriptor&, TcpStreamTracker&) override;
+
+private:
+ TcpSession& session;
+};
+
+#endif
+
--- /dev/null
+//--------------------------------------------------------------------------
+// Copyright (C) 2015-2015 Cisco and/or its affiliates. All rights reserved.
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License Version 2 as published
+// by the Free Software Foundation. You may not use, modify or distribute
+// this program under any other version of the GNU General Public License.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+//--------------------------------------------------------------------------
+
+// tcp_state_fin_wait1.cc author davis mcpherson <davmcphe@cisco.com>
+// Created on: Aug 5, 2015
+
+#include <iostream>
+using namespace std;
+
+#include "tcp_module.h"
+#include "tcp_tracker.h"
+#include "tcp_session.h"
+#include "tcp_normalizer.h"
+#include "tcp_state_fin_wait1.h"
+
+#ifdef UNIT_TEST
+#include "catch/catch.hpp"
+#endif
+
+TcpStateFinWait1::TcpStateFinWait1(TcpStateMachine& tsm, TcpSession& session) :
+ TcpStateHandler(TcpStreamTracker::TCP_FIN_WAIT1, tsm), session(session)
+{
+}
+
+TcpStateFinWait1::~TcpStateFinWait1()
+{
+}
+
+bool TcpStateFinWait1::syn_sent(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
+{
+ TcpTracker& trk = static_cast< TcpTracker& >( tracker );
+
+ return default_state_action(tsd, trk, __func__);
+}
+
+bool TcpStateFinWait1::syn_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
+{
+ TcpTracker& trk = static_cast< TcpTracker& >( tracker );
+
+ return default_state_action(tsd, trk, __func__);
+}
+
+bool TcpStateFinWait1::syn_ack_sent(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
+{
+ TcpTracker& trk = static_cast< TcpTracker& >( tracker );
+
+ return default_state_action(tsd, trk, __func__);
+}
+
+bool TcpStateFinWait1::syn_ack_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
+{
+ TcpTracker& trk = static_cast< TcpTracker& >( tracker );
+
+ return default_state_action(tsd, trk, __func__);
+}
+
+bool TcpStateFinWait1::ack_sent(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
+{
+ TcpTracker& trk = static_cast< TcpTracker& >( tracker );
+
+ return default_state_action(tsd, trk, __func__);
+}
+
+bool TcpStateFinWait1::ack_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
+{
+ TcpTracker& trk = static_cast< TcpTracker& >( tracker );
+
+ return default_state_action(tsd, trk, __func__);
+}
+
+bool TcpStateFinWait1::data_seg_sent(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
+{
+ TcpTracker& trk = static_cast< TcpTracker& >( tracker );
+
+ return default_state_action(tsd, trk, __func__);
+}
+
+bool TcpStateFinWait1::data_seg_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
+{
+ TcpTracker& trk = static_cast< TcpTracker& >( tracker );
+
+ return default_state_action(tsd, trk, __func__);
+}
+
+bool TcpStateFinWait1::fin_sent(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
+{
+ TcpTracker& trk = static_cast< TcpTracker& >( tracker );
+
+ return default_state_action(tsd, trk, __func__);
+}
+
+bool TcpStateFinWait1::fin_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
+{
+ TcpTracker& trk = static_cast< TcpTracker& >( tracker );
+
+ return default_state_action(tsd, trk, __func__);
+}
+
+bool TcpStateFinWait1::rst_sent(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
+{
+ TcpTracker& trk = static_cast< TcpTracker& >( tracker );
+
+ return default_state_action(tsd, trk, __func__);
+}
+
+bool TcpStateFinWait1::rst_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
+{
+ TcpTracker& trk = static_cast< TcpTracker& >( tracker );
+
+ return default_state_action(tsd, trk, __func__);
+}
+
--- /dev/null
+//--------------------------------------------------------------------------
+// Copyright (C) 2015-2015 Cisco and/or its affiliates. All rights reserved.
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License Version 2 as published
+// by the Free Software Foundation. You may not use, modify or distribute
+// this program under any other version of the GNU General Public License.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+//--------------------------------------------------------------------------
+
+// tcp_state_fin_wait1.h author davis mcpherson <davmcphe@@cisco.com>
+// Created on: Aug 5, 2015
+
+#ifndef TCP_STATE_FIN_WAIT1_H
+#define TCP_STATE_FIN_WAIT1_H
+
+#include "stream/libtcp/tcp_state_handler.h"
+
+class TcpSession;
+
+class TcpStateFinWait1 : public TcpStateHandler
+{
+public:
+ TcpStateFinWait1(TcpStateMachine&, TcpSession&);
+ virtual ~TcpStateFinWait1(void);
+
+ bool syn_sent(TcpSegmentDescriptor&, TcpStreamTracker&) override;
+ bool syn_recv(TcpSegmentDescriptor&, TcpStreamTracker&) override;
+ bool syn_ack_sent(TcpSegmentDescriptor&, TcpStreamTracker&) override;
+ bool syn_ack_recv(TcpSegmentDescriptor&, TcpStreamTracker&) override;
+ bool ack_sent(TcpSegmentDescriptor&, TcpStreamTracker&) override;
+ bool ack_recv(TcpSegmentDescriptor&, TcpStreamTracker&) override;
+ bool data_seg_sent(TcpSegmentDescriptor&, TcpStreamTracker&) override;
+ bool data_seg_recv(TcpSegmentDescriptor&, TcpStreamTracker&) override;
+ bool fin_sent(TcpSegmentDescriptor&, TcpStreamTracker&) override;
+ bool fin_recv(TcpSegmentDescriptor&, TcpStreamTracker&) override;
+ bool rst_sent(TcpSegmentDescriptor&, TcpStreamTracker&) override;
+ bool rst_recv(TcpSegmentDescriptor&, TcpStreamTracker&) override;
+
+private:
+ TcpSession& session;
+};
+
+#endif
+
--- /dev/null
+//--------------------------------------------------------------------------
+// Copyright (C) 2015-2015 Cisco and/or its affiliates. All rights reserved.
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License Version 2 as published
+// by the Free Software Foundation. You may not use, modify or distribute
+// this program under any other version of the GNU General Public License.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+//--------------------------------------------------------------------------
+
+// tcp_state_fin_wait2.cc author davis mcpherson <davmcphe@cisco.com>
+// Created on: Aug 5, 2015
+
+#include <iostream>
+using namespace std;
+
+#include "tcp_module.h"
+#include "tcp_tracker.h"
+#include "tcp_session.h"
+#include "tcp_normalizer.h"
+#include "tcp_state_fin_wait2.h"
+
+#ifdef UNIT_TEST
+#include "catch/catch.hpp"
+#endif
+
+TcpStateFinWait2::TcpStateFinWait2(TcpStateMachine& tsm, TcpSession& session) :
+ TcpStateHandler(TcpStreamTracker::TCP_FIN_WAIT2, tsm), session(session)
+{
+}
+
+TcpStateFinWait2::~TcpStateFinWait2()
+{
+}
+
+bool TcpStateFinWait2::syn_sent(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
+{
+ TcpTracker& trk = static_cast< TcpTracker& >( tracker );
+
+ return default_state_action(tsd, trk, __func__);
+}
+
+bool TcpStateFinWait2::syn_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
+{
+ TcpTracker& trk = static_cast< TcpTracker& >( tracker );
+
+ return default_state_action(tsd, trk, __func__);
+}
+
+bool TcpStateFinWait2::syn_ack_sent(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
+{
+ TcpTracker& trk = static_cast< TcpTracker& >( tracker );
+
+ return default_state_action(tsd, trk, __func__);
+}
+
+bool TcpStateFinWait2::syn_ack_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
+{
+ TcpTracker& trk = static_cast< TcpTracker& >( tracker );
+
+ return default_state_action(tsd, trk, __func__);
+}
+
+bool TcpStateFinWait2::ack_sent(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
+{
+ TcpTracker& trk = static_cast< TcpTracker& >( tracker );
+
+ return default_state_action(tsd, trk, __func__);
+}
+
+bool TcpStateFinWait2::ack_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
+{
+ TcpTracker& trk = static_cast< TcpTracker& >( tracker );
+
+ return default_state_action(tsd, trk, __func__);
+}
+
+bool TcpStateFinWait2::data_seg_sent(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
+{
+ TcpTracker& trk = static_cast< TcpTracker& >( tracker );
+
+ return default_state_action(tsd, trk, __func__);
+}
+
+bool TcpStateFinWait2::data_seg_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
+{
+ TcpTracker& trk = static_cast< TcpTracker& >( tracker );
+
+ return default_state_action(tsd, trk, __func__);
+}
+
+bool TcpStateFinWait2::fin_sent(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
+{
+ TcpTracker& trk = static_cast< TcpTracker& >( tracker );
+
+ return default_state_action(tsd, trk, __func__);
+}
+
+bool TcpStateFinWait2::fin_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
+{
+ TcpTracker& trk = static_cast< TcpTracker& >( tracker );
+
+ return default_state_action(tsd, trk, __func__);
+}
+
+bool TcpStateFinWait2::rst_sent(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
+{
+ TcpTracker& trk = static_cast< TcpTracker& >( tracker );
+
+ return default_state_action(tsd, trk, __func__);
+}
+
+bool TcpStateFinWait2::rst_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
+{
+ TcpTracker& trk = static_cast< TcpTracker& >( tracker );
+
+ return default_state_action(tsd, trk, __func__);
+}
+
--- /dev/null
+//--------------------------------------------------------------------------
+// Copyright (C) 2015-2015 Cisco and/or its affiliates. All rights reserved.
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License Version 2 as published
+// by the Free Software Foundation. You may not use, modify or distribute
+// this program under any other version of the GNU General Public License.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+//--------------------------------------------------------------------------
+
+// tcp_state_fin_wait2.h author davis mcpherson <davmcphe@@cisco.com>
+// Created on: Aug 5, 2015
+
+#ifndef TCP_STATE_FIN_WAIT2_H
+#define TCP_STATE_FIN_WAIT2_H
+
+#include "stream/libtcp/tcp_state_handler.h"
+
+class TcpSession;
+
+class TcpStateFinWait2 : public TcpStateHandler
+{
+public:
+ TcpStateFinWait2(TcpStateMachine&, TcpSession&);
+ virtual ~TcpStateFinWait2(void);
+
+ bool syn_sent(TcpSegmentDescriptor&, TcpStreamTracker&) override;
+ bool syn_recv(TcpSegmentDescriptor&, TcpStreamTracker&) override;
+ bool syn_ack_sent(TcpSegmentDescriptor&, TcpStreamTracker&) override;
+ bool syn_ack_recv(TcpSegmentDescriptor&, TcpStreamTracker&) override;
+ bool ack_sent(TcpSegmentDescriptor&, TcpStreamTracker&) override;
+ bool ack_recv(TcpSegmentDescriptor&, TcpStreamTracker&) override;
+ bool data_seg_sent(TcpSegmentDescriptor&, TcpStreamTracker&) override;
+ bool data_seg_recv(TcpSegmentDescriptor&, TcpStreamTracker&) override;
+ bool fin_sent(TcpSegmentDescriptor&, TcpStreamTracker&) override;
+ bool fin_recv(TcpSegmentDescriptor&, TcpStreamTracker&) override;
+ bool rst_sent(TcpSegmentDescriptor&, TcpStreamTracker&) override;
+ bool rst_recv(TcpSegmentDescriptor&, TcpStreamTracker&) override;
+
+private:
+ TcpSession& session;
+};
+
+#endif
+
--- /dev/null
+//--------------------------------------------------------------------------
+// Copyright (C) 2015-2015 Cisco and/or its affiliates. All rights reserved.
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License Version 2 as published
+// by the Free Software Foundation. You may not use, modify or distribute
+// this program under any other version of the GNU General Public License.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+//--------------------------------------------------------------------------
+
+// tcp_state_last_ack.cc author davis mcpherson <davmcphe@cisco.com>
+// Created on: Aug 5, 2015
+
+#include <iostream>
+using namespace std;
+
+#include "tcp_module.h"
+#include "tcp_tracker.h"
+#include "tcp_session.h"
+#include "tcp_normalizer.h"
+#include "tcp_state_last_ack.h"
+
+#ifdef UNIT_TEST
+#include "catch/catch.hpp"
+#endif
+
+TcpStateLastAck::TcpStateLastAck(TcpStateMachine& tsm, TcpSession& session) :
+ TcpStateHandler(TcpStreamTracker::TCP_LAST_ACK, tsm), session(session)
+{
+}
+
+TcpStateLastAck::~TcpStateLastAck()
+{
+}
+
+bool TcpStateLastAck::syn_sent(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
+{
+ TcpTracker& trk = static_cast< TcpTracker& >( tracker );
+
+ return default_state_action(tsd, trk, __func__);
+}
+
+bool TcpStateLastAck::syn_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
+{
+ TcpTracker& trk = static_cast< TcpTracker& >( tracker );
+
+ return default_state_action(tsd, trk, __func__);
+}
+
+bool TcpStateLastAck::syn_ack_sent(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
+{
+ TcpTracker& trk = static_cast< TcpTracker& >( tracker );
+
+ return default_state_action(tsd, trk, __func__);
+}
+
+bool TcpStateLastAck::syn_ack_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
+{
+ TcpTracker& trk = static_cast< TcpTracker& >( tracker );
+
+ return default_state_action(tsd, trk, __func__);
+}
+
+bool TcpStateLastAck::ack_sent(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
+{
+ TcpTracker& trk = static_cast< TcpTracker& >( tracker );
+
+ return default_state_action(tsd, trk, __func__);
+}
+
+bool TcpStateLastAck::ack_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
+{
+ TcpTracker& trk = static_cast< TcpTracker& >( tracker );
+
+ return default_state_action(tsd, trk, __func__);
+}
+
+bool TcpStateLastAck::data_seg_sent(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
+{
+ TcpTracker& trk = static_cast< TcpTracker& >( tracker );
+
+ return default_state_action(tsd, trk, __func__);
+}
+
+bool TcpStateLastAck::data_seg_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
+{
+ TcpTracker& trk = static_cast< TcpTracker& >( tracker );
+
+ return default_state_action(tsd, trk, __func__);
+}
+
+bool TcpStateLastAck::fin_sent(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
+{
+ TcpTracker& trk = static_cast< TcpTracker& >( tracker );
+
+ return default_state_action(tsd, trk, __func__);
+}
+
+bool TcpStateLastAck::fin_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
+{
+ TcpTracker& trk = static_cast< TcpTracker& >( tracker );
+
+ return default_state_action(tsd, trk, __func__);
+}
+
+bool TcpStateLastAck::rst_sent(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
+{
+ TcpTracker& trk = static_cast< TcpTracker& >( tracker );
+
+ return default_state_action(tsd, trk, __func__);
+}
+
+bool TcpStateLastAck::rst_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
+{
+ TcpTracker& trk = static_cast< TcpTracker& >( tracker );
+
+ return default_state_action(tsd, trk, __func__);
+}
+
--- /dev/null
+//--------------------------------------------------------------------------
+// Copyright (C) 2015-2015 Cisco and/or its affiliates. All rights reserved.
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License Version 2 as published
+// by the Free Software Foundation. You may not use, modify or distribute
+// this program under any other version of the GNU General Public License.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+//--------------------------------------------------------------------------
+
+// tcp_state_last_ack.h author davis mcpherson <davmcphe@cisco.com>
+// Created on: Aug 5, 2015
+
+#ifndef TCP_STATE_LAST_ACK_H
+#define TCP_STATE_LAST_ACK_H
+
+#include "stream/libtcp/tcp_state_handler.h"
+
+class TcpSession;
+
+class TcpStateLastAck : public TcpStateHandler
+{
+public:
+ TcpStateLastAck(TcpStateMachine&, TcpSession&);
+ virtual ~TcpStateLastAck(void);
+
+ bool syn_sent(TcpSegmentDescriptor&, TcpStreamTracker&) override;
+ bool syn_recv(TcpSegmentDescriptor&, TcpStreamTracker&) override;
+ bool syn_ack_sent(TcpSegmentDescriptor&, TcpStreamTracker&) override;
+ bool syn_ack_recv(TcpSegmentDescriptor&, TcpStreamTracker&) override;
+ bool ack_sent(TcpSegmentDescriptor&, TcpStreamTracker&) override;
+ bool ack_recv(TcpSegmentDescriptor&, TcpStreamTracker&) override;
+ bool data_seg_sent(TcpSegmentDescriptor&, TcpStreamTracker&) override;
+ bool data_seg_recv(TcpSegmentDescriptor&, TcpStreamTracker&) override;
+ bool fin_sent(TcpSegmentDescriptor&, TcpStreamTracker&) override;
+ bool fin_recv(TcpSegmentDescriptor&, TcpStreamTracker&) override;
+ bool rst_sent(TcpSegmentDescriptor&, TcpStreamTracker&) override;
+ bool rst_recv(TcpSegmentDescriptor&, TcpStreamTracker&) override;
+
+private:
+ TcpSession& session;
+};
+
+#endif
+
--- /dev/null
+//--------------------------------------------------------------------------
+// Copyright (C) 2015-2015 Cisco and/or its affiliates. All rights reserved.
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License Version 2 as published
+// by the Free Software Foundation. You may not use, modify or distribute
+// this program under any other version of the GNU General Public License.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+//--------------------------------------------------------------------------
+
+// tcp_state_listen.cc author davis mcpherson <davmcphe@@cisco.com>
+// Created on: Jul 30, 2015
+
+#include "tcp_module.h"
+#include "tcp_tracker.h"
+#include "tcp_session.h"
+#include "tcp_normalizer.h"
+#include "tcp_state_listen.h"
+
+TcpStateListen::TcpStateListen(TcpStateMachine& tsm, TcpSession&) :
+ TcpStateHandler(TcpStreamTracker::TCP_LISTEN, tsm), session(session)
+{
+}
+
+TcpStateListen::~TcpStateListen()
+{
+}
+
+bool TcpStateListen::syn_sent(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
+{
+ TcpTracker& trk = static_cast< TcpTracker& >( tracker );
+
+ return default_state_action(tsd, trk, __func__);
+}
+
+bool TcpStateListen::syn_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
+{
+ TcpTracker& trk = static_cast< TcpTracker& >( tracker );
+
+ return default_state_action(tsd, trk, __func__);
+}
+
+bool TcpStateListen::syn_ack_sent(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
+{
+ TcpTracker& trk = static_cast< TcpTracker& >( tracker );
+
+ return default_state_action(tsd, trk, __func__);
+}
+
+bool TcpStateListen::syn_ack_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
+{
+ TcpTracker& trk = static_cast< TcpTracker& >( tracker );
+
+ return default_state_action(tsd, trk, __func__);
+}
+
+bool TcpStateListen::ack_sent(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
+{
+ TcpTracker& trk = static_cast< TcpTracker& >( tracker );
+
+ return default_state_action(tsd, trk, __func__);
+}
+
+bool TcpStateListen::ack_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
+{
+ TcpTracker& trk = static_cast< TcpTracker& >( tracker );
+
+ return default_state_action(tsd, trk, __func__);
+}
+
+bool TcpStateListen::data_seg_sent(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
+{
+ TcpTracker& trk = static_cast< TcpTracker& >( tracker );
+
+ return default_state_action(tsd, trk, __func__);
+}
+
+bool TcpStateListen::data_seg_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
+{
+ TcpTracker& trk = static_cast< TcpTracker& >( tracker );
+
+ return default_state_action(tsd, trk, __func__);
+}
+
+bool TcpStateListen::fin_sent(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
+{
+ TcpTracker& trk = static_cast< TcpTracker& >( tracker );
+
+ return default_state_action(tsd, trk, __func__);
+}
+
+bool TcpStateListen::fin_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
+{
+ TcpTracker& trk = static_cast< TcpTracker& >( tracker );
+
+ return default_state_action(tsd, trk, __func__);
+}
+
+bool TcpStateListen::rst_sent(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
+{
+ TcpTracker& trk = static_cast< TcpTracker& >( tracker );
+
+ return default_state_action(tsd, trk, __func__);
+}
+
+bool TcpStateListen::rst_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
+{
+ TcpTracker& trk = static_cast< TcpTracker& >( tracker );
+
+ return default_state_action(tsd, trk, __func__);
+}
+
--- /dev/null
+//--------------------------------------------------------------------------
+// Copyright (C) 2015-2015 Cisco and/or its affiliates. All rights reserved.
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License Version 2 as published
+// by the Free Software Foundation. You may not use, modify or distribute
+// this program under any other version of the GNU General Public License.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+//--------------------------------------------------------------------------
+
+// tcp_listen_state.h author davis mcpherson <davmcphe@cisco.com>
+// Created on: Jul 30, 2015
+
+#ifndef TCP_STATE_LISTEN_H
+#define TCP_STATE_LISTEN_H
+
+#include "stream/libtcp/tcp_state_handler.h"
+
+class TcpSession;
+
+class TcpStateListen : public TcpStateHandler
+{
+public:
+ TcpStateListen(TcpStateMachine&, TcpSession&);
+ virtual ~TcpStateListen(void);
+
+ bool syn_sent(TcpSegmentDescriptor&, TcpStreamTracker&) override;
+ bool syn_recv(TcpSegmentDescriptor&, TcpStreamTracker&) override;
+ bool syn_ack_sent(TcpSegmentDescriptor&, TcpStreamTracker&) override;
+ bool syn_ack_recv(TcpSegmentDescriptor&, TcpStreamTracker&) override;
+ bool ack_sent(TcpSegmentDescriptor&, TcpStreamTracker&) override;
+ bool ack_recv(TcpSegmentDescriptor&, TcpStreamTracker&) override;
+ bool data_seg_sent(TcpSegmentDescriptor&, TcpStreamTracker&) override;
+ bool data_seg_recv(TcpSegmentDescriptor&, TcpStreamTracker&) override;
+ bool fin_sent(TcpSegmentDescriptor&, TcpStreamTracker&) override;
+ bool fin_recv(TcpSegmentDescriptor&, TcpStreamTracker&) override;
+ bool rst_sent(TcpSegmentDescriptor&, TcpStreamTracker&) override;
+ bool rst_recv(TcpSegmentDescriptor&, TcpStreamTracker&) override;
+
+private:
+ TcpSession& session;
+};
+
+#endif
+
--- /dev/null
+//--------------------------------------------------------------------------
+// Copyright (C) 2015-2015 Cisco and/or its affiliates. All rights reserved.
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License Version 2 as published
+// by the Free Software Foundation. You may not use, modify or distribute
+// this program under any other version of the GNU General Public License.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+//--------------------------------------------------------------------------
+
+// tcp_state_none.cc author davis mcpherson <davmcphe@@cisco.com>
+// Created on: Jul 30, 2015
+
+#include "stream/stream.h"
+
+#include "tcp_module.h"
+#include "tcp_tracker.h"
+#include "tcp_session.h"
+#include "tcp_normalizer.h"
+#include "tcp_state_none.h"
+
+#ifdef UNIT_TEST
+#include "catch/catch.hpp"
+#include "stream/libtcp/stream_tcp_unit_test.h"
+#endif
+
+TcpStateNone::TcpStateNone(TcpStateMachine& tsm, TcpSession& session) :
+ TcpStateHandler(TcpStreamTracker::TCP_STATE_NONE, tsm), session(session)
+{
+}
+
+TcpStateNone::~TcpStateNone()
+{
+}
+
+bool TcpStateNone::syn_sent(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
+{
+ Flow* flow = tsd.get_flow();
+ TcpTracker& trk = static_cast< TcpTracker& >( tracker );
+
+ flow->ssn_state.direction = FROM_CLIENT;
+ flow->session_state |= STREAM_STATE_SYN;
+
+ if ( trk.is_3whs_required() || ( tsd.has_wscale() & TF_WSCALE ) ||
+ ( tsd.get_pkt()->dsize > 0 ) )
+ {
+ trk.init_on_syn_sent(tsd);
+ session.init_new_tcp_session(tsd);
+ tcpStats.sessions_on_syn++;
+ }
+
+ return true;
+}
+
+bool TcpStateNone::syn_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
+{
+ TcpTracker& trk = static_cast< TcpTracker& >( tracker );
+
+ if ( trk.is_3whs_required() || ( tsd.has_wscale() & TF_WSCALE ) ||
+ ( tsd.get_pkt()->dsize > 0 ) )
+ {
+ trk.init_on_syn_recv(tsd);
+ trk.normalizer->ecn_tracker(tsd.get_tcph(), trk.is_3whs_required() );
+ }
+
+ return true;
+}
+
+bool TcpStateNone::syn_ack_sent(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
+{
+ Flow* flow = tsd.get_flow();
+ TcpTracker& trk = static_cast< TcpTracker& >( tracker );
+
+ /* SYN-ACK from server */
+ if ( ( flow->session_state == STREAM_STATE_NONE)
+ || ( flow->get_session_flags() & SSNFLAG_RESET ) )
+ {
+ DebugMessage(DEBUG_STREAM_STATE,
+ "Stream SYN|ACK PACKET, set session directioon to FROM_SERVER.\n");
+ flow->ssn_state.direction = FROM_SERVER;
+ }
+
+ flow->session_state |= STREAM_STATE_SYN_ACK;
+
+ if ( !trk.is_3whs_required() || session.config->midstream_allowed(tsd.get_pkt()) )
+ {
+ trk.init_on_synack_sent(tsd);
+ session.init_new_tcp_session(tsd);
+ tcpStats.sessions_on_syn_ack++;
+ }
+
+ return true;
+}
+
+bool TcpStateNone::syn_ack_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
+{
+ TcpTracker& trk = static_cast< TcpTracker& >( tracker );
+
+ if ( !trk.is_3whs_required() || session.config->midstream_allowed(tsd.get_pkt()) )
+ {
+ trk.init_on_synack_recv(tsd);
+ }
+
+ trk.normalizer->ecn_tracker(tsd.get_tcph(), trk.is_3whs_required() );
+
+ return true;
+}
+
+bool TcpStateNone::ack_sent(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
+{
+ Flow* flow = tsd.get_flow();
+ TcpTracker& trk = static_cast< TcpTracker& >( tracker );
+
+ if ( !tsd.get_tcph()->is_rst() && ( flow->session_state & STREAM_STATE_SYN_ACK ) )
+ {
+ /* FIXIT: do we need to verify the ACK field is >= the seq of the SYN-ACK?
+ 3-way Handshake complete, create TCP session */
+ flow->session_state |= ( STREAM_STATE_ACK | STREAM_STATE_ESTABLISHED );
+ trk.init_on_3whs_ack_sent(tsd);
+ session.init_new_tcp_session(tsd);
+ session.update_perf_base_state(&sfBase, TcpStreamTracker::TCP_ESTABLISHED);
+ tcpStats.sessions_on_3way++;
+ }
+
+ return true;
+}
+
+bool TcpStateNone::ack_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
+{
+ Flow* flow = tsd.get_flow();
+ TcpTracker& trk = static_cast< TcpTracker& >( tracker );
+
+ 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.is_3whs_required() );
+ }
+
+ return true;
+}
+
+bool TcpStateNone::data_seg_sent(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
+{
+ TcpTracker& trk = static_cast< TcpTracker& >( tracker );
+
+ // FIXIT - are these necessary (see checks in TcpSession::process, but should get rid of those
+ if ( !trk.is_3whs_required() || session.config->midstream_allowed(tsd.get_pkt()) )
+ {
+ Flow* flow = tsd.get_flow();
+
+ flow->session_state |= STREAM_STATE_MIDSTREAM;
+ flow->set_session_flags(SSNFLAG_MIDSTREAM);
+
+ if (tsd.get_pkt()->ptrs.sp > tsd.get_pkt()->ptrs.dp)
+ {
+ flow->ssn_state.direction = FROM_CLIENT;
+ flow->set_session_flags(SSNFLAG_SEEN_CLIENT);
+ }
+ else
+ {
+ flow->ssn_state.direction = FROM_SERVER;
+ flow->set_session_flags(SSNFLAG_SEEN_SERVER);
+ }
+
+ trk.init_on_data_seg_sent(tsd);
+ session.init_new_tcp_session(tsd);
+
+ if ( flow->session_state & STREAM_STATE_ESTABLISHED )
+ session.update_perf_base_state(&sfBase, TcpStreamTracker::TCP_ESTABLISHED);
+
+ tcpStats.sessions_on_data++;
+ }
+
+ return true;
+}
+
+bool TcpStateNone::data_seg_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
+{
+ TcpTracker& trk = static_cast< TcpTracker& >( tracker );
+
+ if ( !trk.is_3whs_required() || session.config->midstream_allowed(tsd.get_pkt()) )
+ {
+ Flow* flow = tsd.get_flow();
+
+ flow->session_state |= STREAM_STATE_MIDSTREAM;
+ flow->set_session_flags(SSNFLAG_MIDSTREAM);
+
+ if (tsd.get_pkt()->ptrs.sp > tsd.get_pkt()->ptrs.dp)
+ {
+ flow->ssn_state.direction = FROM_CLIENT;
+ flow->set_session_flags(SSNFLAG_SEEN_CLIENT);
+ }
+ else
+ {
+ flow->ssn_state.direction = FROM_SERVER;
+ flow->set_session_flags(SSNFLAG_SEEN_SERVER);
+ }
+
+ trk.init_on_data_seg_recv(tsd);
+ trk.normalizer->ecn_tracker(tsd.get_tcph(), trk.is_3whs_required() );
+ }
+
+ return true;
+}
+
+bool TcpStateNone::fin_sent(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
+{
+ TcpTracker& trk = static_cast< TcpTracker& >( tracker );
+
+ return default_state_action(tsd, trk, __func__);
+}
+
+bool TcpStateNone::fin_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
+{
+ TcpTracker& trk = static_cast< TcpTracker& >( tracker );
+
+ return default_state_action(tsd, trk, __func__);
+}
+
+bool TcpStateNone::rst_sent(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
+{
+ TcpTracker& trk = static_cast< TcpTracker& >( tracker );
+
+ return default_state_action(tsd, trk, __func__);
+}
+
+bool TcpStateNone::rst_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
+{
+ TcpTracker& trk = static_cast< TcpTracker& >( tracker );
+
+ return default_state_action(tsd, trk, __func__);
+}
+
+#ifdef FOO // FIXIT - UNIT_TEST need work!!
+#include "tcp_normalizers.h"
+#include "tcp_reassemblers.h"
+
+TEST_CASE("TCP State None", "[tcp_none_state][stream_tcp]")
+{
+ // initialization code here
+ Flow* flow = new Flow;
+ TcpTracker* ctrk = new TcpTracker(true);
+ TcpTracker* strk = new TcpTracker(false);
+ TcpEventLogger* tel = new TcpEventLogger;
+ TcpSession* session = new TcpSession(flow);
+ TcpStateMachine* tsm = new TcpStateMachine;
+ TcpStateHandler* tsh = new TcpStateNone(*tsm, *session);
+ ctrk->normalizer = TcpNormalizerFactory::create(session, StreamPolicy::OS_LINUX, ctrk, strk);
+ strk->normalizer = TcpNormalizerFactory::create(session, StreamPolicy::OS_LINUX, strk, ctrk);
+ ctrk->reassembler = TcpReassemblerFactory::create(session, ctrk, StreamPolicy::OS_LINUX,
+ false);
+ strk->reassembler = TcpReassemblerFactory::create(session, strk, StreamPolicy::OS_LINUX, true);
+
+ SECTION("syn_packet")
+ {
+ Packet* pkt = get_syn_packet(flow);
+ REQUIRE( ( pkt != nullptr ) );
+
+ SECTION("syn_sent")
+ {
+ flow->ssn_state.direction = FROM_CLIENT;
+ TcpSegmentDescriptor tsd(flow, pkt, tel);
+ ctrk->set_tcp_event(tsd);
+ ctrk->set_require_3whs(false);
+ tsh->eval(tsd, *ctrk);
+ CHECK(TcpStreamTracker::TCP_SYN_SENT_EVENT == ctrk->get_tcp_event() );
+ //CHECK( ( ctrk->get_iss() == 9050 ) );
+ //CHECK( ( ctrk->get_snd_una() == 9051 ) );
+ //CHECK( ( ctrk->get_snd_nxt() == 9050 ) );
+ //CHECK( ( ctrk->get_snd_wnd() == 8192 ) );
+ }
+
+ SECTION("syn_recv")
+ {
+ flow->ssn_state.direction = FROM_SERVER;
+ TcpSegmentDescriptor tsd(flow, pkt, tel);
+ ctrk->set_tcp_event(tsd);
+ tsh->eval(tsd, *ctrk);
+ CHECK( ( tsh->get_tcp_event() == ctrk->get_tcp_event() ) );
+ }
+
+ delete pkt;
+ }
+
+ SECTION("syn_ack_packet")
+ {
+ Packet* pkt = get_syn_ack_packet(flow);
+ REQUIRE( ( pkt != nullptr ) );
+
+ SECTION("syn_ack_sent")
+ {
+ flow->ssn_state.direction = FROM_CLIENT;
+ TcpSegmentDescriptor tsd(flow, pkt, tel);
+ ctrk->set_tcp_event(tsd);
+ ctrk->set_require_3whs(false);
+ tsh->eval(tsd, *ctrk);
+ CHECK( ( tsh->get_tcp_event() == ctrk->get_tcp_event() ) );
+ }
+
+ SECTION("syn_ack_recv")
+ {
+ flow->ssn_state.direction = FROM_SERVER;
+ TcpSegmentDescriptor tsd(flow, pkt, tel);
+ ctrk->set_tcp_event(tsd);
+ ctrk->set_require_3whs(false);
+ tsh->eval(tsd, *ctrk);
+ CHECK( ( tsh->get_tcp_event() == ctrk->get_tcp_event() ) );
+ }
+
+ delete pkt;
+ }
+
+ SECTION("ack_packet")
+ {
+ Packet* pkt = get_ack_packet(flow);
+ REQUIRE( ( pkt != nullptr ) );
+
+ SECTION("ack_sent")
+ {
+ flow->ssn_state.direction = FROM_CLIENT;
+ TcpSegmentDescriptor tsd(flow, pkt, tel);
+ ctrk->set_tcp_event(tsd);
+ ctrk->set_require_3whs(false);
+ tsh->eval(tsd, *ctrk);
+ CHECK( ( tsh->get_tcp_event() == ctrk->get_tcp_event() ) );
+ }
+
+ SECTION("ack_recv")
+ {
+ flow->ssn_state.direction = FROM_SERVER;
+ TcpSegmentDescriptor tsd(flow, pkt, tel);
+ ctrk->set_tcp_event(tsd);
+ ctrk->set_require_3whs(false);
+ tsh->eval(tsd, *ctrk);
+ CHECK( ( tsh->get_tcp_event() == ctrk->get_tcp_event() ) );
+ }
+
+ delete pkt;
+ }
+
+ SECTION("data_seg_packet")
+ {
+ Packet* pkt = get_data_packet(flow);
+ REQUIRE( ( pkt != nullptr ) );
+
+ SECTION("data_seg_sent")
+ {
+ flow->ssn_state.direction = FROM_CLIENT;
+ TcpSegmentDescriptor tsd(flow, pkt, tel);
+ ctrk->set_tcp_event(tsd);
+ ctrk->set_require_3whs(false);
+ tsh->eval(tsd, *ctrk);
+ CHECK( ( tsh->get_tcp_event() == ctrk->get_tcp_event() ) );
+ }
+
+ SECTION("data_seg_recv")
+ {
+ flow->ssn_state.direction = FROM_SERVER;
+ TcpSegmentDescriptor tsd(flow, pkt, tel);
+ ctrk->set_tcp_event(tsd);
+ ctrk->set_require_3whs(false);
+ tsh->eval(tsd, *ctrk);
+ CHECK( ( tsh->get_tcp_event() == ctrk->get_tcp_event() ) );
+ }
+
+ delete pkt;
+ }
+
+ SECTION("fin_packet")
+ {
+ Packet* pkt = get_fin_packet(flow);
+ REQUIRE( ( pkt != nullptr ) );
+
+ SECTION("fin_sent")
+ {
+ flow->ssn_state.direction = FROM_CLIENT;
+ TcpSegmentDescriptor tsd(flow, pkt, tel);
+ ctrk->set_tcp_event(tsd);
+ ctrk->set_require_3whs(false);
+ tsh->eval(tsd, *ctrk);
+ CHECK( ( tsh->get_tcp_event() == ctrk->get_tcp_event() ) );
+ }
+
+ SECTION("fin_recv")
+ {
+ flow->ssn_state.direction = FROM_SERVER;
+ TcpSegmentDescriptor tsd(flow, pkt, tel);
+ ctrk->set_tcp_event(tsd);
+ ctrk->set_require_3whs(false);
+ tsh->eval(tsd, *ctrk);
+ CHECK( ( tsh->get_tcp_event() == ctrk->get_tcp_event() ) );
+ }
+
+ delete pkt;
+ }
+
+ SECTION("rst_packet")
+ {
+ Packet* pkt = get_rst_packet(flow);
+ REQUIRE( ( pkt != nullptr ));
+
+ SECTION("rst_sent")
+ {
+ flow->ssn_state.direction = FROM_CLIENT;
+ TcpSegmentDescriptor tsd(flow, pkt, tel);
+ ctrk->set_tcp_event(tsd);
+ ctrk->set_require_3whs(false);
+ tsh->eval(tsd, *ctrk);
+ CHECK( ( tsh->get_tcp_event() == ctrk->get_tcp_event() ));
+ }
+
+ SECTION("rst_recv")
+ {
+ flow->ssn_state.direction = FROM_SERVER;
+ TcpSegmentDescriptor tsd(flow, pkt, tel);
+ ctrk->set_tcp_event(tsd);
+ ctrk->set_require_3whs(false);
+ tsh->eval(tsd, *ctrk);
+ CHECK( ( tsh->get_tcp_event() == ctrk->get_tcp_event() ) );
+ }
+
+ delete pkt;
+ }
+
+ delete flow;
+ delete tsh;
+ delete ctrk;
+ delete strk;
+}
+
+#endif
+
--- /dev/null
+//--------------------------------------------------------------------------
+// Copyright (C) 2015-2015 Cisco and/or its affiliates. All rights reserved.
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License Version 2 as published
+// by the Free Software Foundation. You may not use, modify or distribute
+// this program under any other version of the GNU General Public License.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+//--------------------------------------------------------------------------
+
+// tcp_state_none.h author davis mcpherson <davmcphe@cisco.com>
+// Created on: Jul 30, 2015
+
+#ifndef TCP_STATE_NONE_H
+#define TCP_STATE_NONE_H
+
+#include "stream/libtcp/tcp_state_handler.h"
+
+class TcpSession;
+
+class TcpStateNone : public TcpStateHandler
+{
+public:
+ TcpStateNone(TcpStateMachine&, TcpSession&);
+ virtual ~TcpStateNone(void);
+
+ bool syn_sent(TcpSegmentDescriptor&, TcpStreamTracker&) override;
+ bool syn_recv(TcpSegmentDescriptor&, TcpStreamTracker&) override;
+ bool syn_ack_sent(TcpSegmentDescriptor&, TcpStreamTracker&) override;
+ bool syn_ack_recv(TcpSegmentDescriptor&, TcpStreamTracker&) override;
+ bool ack_sent(TcpSegmentDescriptor&, TcpStreamTracker&) override;
+ bool ack_recv(TcpSegmentDescriptor&, TcpStreamTracker&) override;
+ bool data_seg_sent(TcpSegmentDescriptor&, TcpStreamTracker&) override;
+ bool data_seg_recv(TcpSegmentDescriptor&, TcpStreamTracker&) override;
+ bool fin_sent(TcpSegmentDescriptor&, TcpStreamTracker&) override;
+ bool fin_recv(TcpSegmentDescriptor&, TcpStreamTracker&) override;
+ bool rst_sent(TcpSegmentDescriptor&, TcpStreamTracker&) override;
+ bool rst_recv(TcpSegmentDescriptor&, TcpStreamTracker&) override;
+
+private:
+ TcpSession& session;
+};
+
+#endif
+
--- /dev/null
+//--------------------------------------------------------------------------
+// Copyright (C) 2015-2015 Cisco and/or its affiliates. All rights reserved.
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License Version 2 as published
+// by the Free Software Foundation. You may not use, modify or distribute
+// this program under any other version of the GNU General Public License.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+//--------------------------------------------------------------------------
+
+// tcp_state_syn_recv.cc author davis mcpherson <davmcphe@@cisco.com>
+// Created on: Aug 5, 2015
+
+#include <iostream>
+using namespace std;
+
+#include "tcp_module.h"
+#include "tcp_tracker.h"
+#include "tcp_session.h"
+#include "tcp_normalizer.h"
+#include "tcp_state_syn_recv.h"
+
+TcpStateSynRecv::TcpStateSynRecv(TcpStateMachine& tsm, TcpSession& session) :
+ TcpStateHandler(TcpStreamTracker::TCP_SYN_RECV, tsm), session(session)
+{
+}
+
+TcpStateSynRecv::~TcpStateSynRecv()
+{
+}
+
+bool TcpStateSynRecv::syn_sent(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
+{
+ TcpTracker& trk = static_cast< TcpTracker& >( tracker );
+
+ return default_state_action(tsd, trk, __func__);
+}
+
+bool TcpStateSynRecv::syn_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
+{
+ TcpTracker& trk = static_cast< TcpTracker& >( tracker );
+
+ return default_state_action(tsd, trk, __func__);
+}
+
+bool TcpStateSynRecv::syn_ack_sent(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
+{
+ TcpTracker& trk = static_cast< TcpTracker& >( tracker );
+
+ return default_state_action(tsd, trk, __func__);
+}
+
+bool TcpStateSynRecv::syn_ack_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
+{
+ TcpTracker& trk = static_cast< TcpTracker& >( tracker );
+
+ return default_state_action(tsd, trk, __func__);
+}
+
+bool TcpStateSynRecv::ack_sent(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
+{
+ TcpTracker& trk = static_cast< TcpTracker& >( tracker );
+
+ return default_state_action(tsd, trk, __func__);
+}
+
+bool TcpStateSynRecv::ack_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
+{
+ TcpTracker& trk = static_cast< TcpTracker& >( tracker );
+
+ return default_state_action(tsd, trk, __func__);
+}
+
+bool TcpStateSynRecv::data_seg_sent(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
+{
+ TcpTracker& trk = static_cast< TcpTracker& >( tracker );
+
+ return default_state_action(tsd, trk, __func__);
+}
+
+bool TcpStateSynRecv::data_seg_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
+{
+ TcpTracker& trk = static_cast< TcpTracker& >( tracker );
+
+ return default_state_action(tsd, trk, __func__);
+}
+
+bool TcpStateSynRecv::fin_sent(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
+{
+ TcpTracker& trk = static_cast< TcpTracker& >( tracker );
+
+ return default_state_action(tsd, trk, __func__);
+}
+
+bool TcpStateSynRecv::fin_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
+{
+ TcpTracker& trk = static_cast< TcpTracker& >( tracker );
+
+ return default_state_action(tsd, trk, __func__);
+}
+
+bool TcpStateSynRecv::rst_sent(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
+{
+ TcpTracker& trk = static_cast< TcpTracker& >( tracker );
+
+ return default_state_action(tsd, trk, __func__);
+}
+
+bool TcpStateSynRecv::rst_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
+{
+ TcpTracker& trk = static_cast< TcpTracker& >( tracker );
+
+ return default_state_action(tsd, trk, __func__);
+}
+
// tcp_syn_recv_state.h author davis mcpherson <davmcphe@@cisco.com>
// Created on: Aug 5, 2015
-#ifndef TCP_SYN_RECV_STATE_H
-#define TCP_SYN_RECV_STATE_H
+#ifndef TCP_STATE_SYN_RECV_H
+#define TCP_STATE_SYN_RECV_H
#include "stream/libtcp/tcp_state_handler.h"
-class TcpSynRecvState: public TcpStateHandler
+class TcpSession;
+
+class TcpStateSynRecv : public TcpStateHandler
{
public:
- TcpSynRecvState();
- virtual ~TcpSynRecvState();
-
- void syn_sent(TcpSegmentDescriptor&, TcpStreamTracker&);
- void syn_recv(TcpSegmentDescriptor&, TcpStreamTracker&);
- void syn_ack_sent(TcpSegmentDescriptor&, TcpStreamTracker&);
- void syn_ack_recv(TcpSegmentDescriptor&, TcpStreamTracker&);
- void ack_sent(TcpSegmentDescriptor&, TcpStreamTracker&);
- void ack_recv(TcpSegmentDescriptor&, TcpStreamTracker&);
- void data_seg_sent(TcpSegmentDescriptor&, TcpStreamTracker&);
- void data_seg_recv(TcpSegmentDescriptor&, TcpStreamTracker&);
- void fin_sent(TcpSegmentDescriptor&, TcpStreamTracker&);
- void fin_recv(TcpSegmentDescriptor&, TcpStreamTracker&);
- void rst_sent(TcpSegmentDescriptor&, TcpStreamTracker&);
- void rst_recv(TcpSegmentDescriptor&, TcpStreamTracker&);
+ TcpStateSynRecv(TcpStateMachine&, TcpSession&);
+ virtual ~TcpStateSynRecv(void);
+
+ bool syn_sent(TcpSegmentDescriptor&, TcpStreamTracker&) override;
+ bool syn_recv(TcpSegmentDescriptor&, TcpStreamTracker&) override;
+ bool syn_ack_sent(TcpSegmentDescriptor&, TcpStreamTracker&) override;
+ bool syn_ack_recv(TcpSegmentDescriptor&, TcpStreamTracker&) override;
+ bool ack_sent(TcpSegmentDescriptor&, TcpStreamTracker&) override;
+ bool ack_recv(TcpSegmentDescriptor&, TcpStreamTracker&) override;
+ bool data_seg_sent(TcpSegmentDescriptor&, TcpStreamTracker&) override;
+ bool data_seg_recv(TcpSegmentDescriptor&, TcpStreamTracker&) override;
+ bool fin_sent(TcpSegmentDescriptor&, TcpStreamTracker&) override;
+ bool fin_recv(TcpSegmentDescriptor&, TcpStreamTracker&) override;
+ bool rst_sent(TcpSegmentDescriptor&, TcpStreamTracker&) override;
+ bool rst_recv(TcpSegmentDescriptor&, TcpStreamTracker&) override;
+
+private:
+ TcpSession& session;
};
#endif
+
--- /dev/null
+//--------------------------------------------------------------------------
+// Copyright (C) 2015-2015 Cisco and/or its affiliates. All rights reserved.
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License Version 2 as published
+// by the Free Software Foundation. You may not use, modify or distribute
+// this program under any other version of the GNU General Public License.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+//--------------------------------------------------------------------------
+
+// tcp_state_syn_sent.cc author davis mcpherson <davmcphe@cisco.com>
+// Created on: Aug 5, 2015
+
+#include <iostream>
+using namespace std;
+
+#include "tcp_module.h"
+#include "tcp_tracker.h"
+#include "tcp_session.h"
+#include "tcp_normalizer.h"
+#include "tcp_state_syn_sent.h"
+
+#ifdef UNIT_TEST
+#include "catch/catch.hpp"
+#endif
+
+TcpStateSynSent::TcpStateSynSent(TcpStateMachine& tsm, TcpSession& session) :
+ TcpStateHandler(TcpStreamTracker::TCP_SYN_SENT, tsm), session(session)
+{
+}
+
+TcpStateSynSent::~TcpStateSynSent()
+{
+}
+
+bool TcpStateSynSent::syn_sent(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
+{
+ TcpTracker& trk = static_cast< TcpTracker& >( tracker );
+
+ return default_state_action(tsd, trk, __func__);
+}
+
+bool TcpStateSynSent::syn_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
+{
+ TcpTracker& trk = static_cast< TcpTracker& >( tracker );
+
+ return default_state_action(tsd, trk, __func__);
+}
+
+bool TcpStateSynSent::syn_ack_sent(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
+{
+ TcpTracker& trk = static_cast< TcpTracker& >( tracker );
+
+ return default_state_action(tsd, trk, __func__);
+}
+
+bool TcpStateSynSent::syn_ack_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
+{
+ TcpTracker& trk = static_cast< TcpTracker& >( tracker );
+
+ return default_state_action(tsd, trk, __func__);
+}
+
+bool TcpStateSynSent::ack_sent(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
+{
+ TcpTracker& trk = static_cast< TcpTracker& >( tracker );
+
+ return default_state_action(tsd, trk, __func__);
+}
+
+bool TcpStateSynSent::ack_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
+{
+ TcpTracker& trk = static_cast< TcpTracker& >( tracker );
+
+ return default_state_action(tsd, trk, __func__);
+}
+
+bool TcpStateSynSent::data_seg_sent(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
+{
+ TcpTracker& trk = static_cast< TcpTracker& >( tracker );
+
+ return default_state_action(tsd, trk, __func__);
+}
+
+bool TcpStateSynSent::data_seg_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
+{
+ TcpTracker& trk = static_cast< TcpTracker& >( tracker );
+
+ return default_state_action(tsd, trk, __func__);
+}
+
+bool TcpStateSynSent::fin_sent(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
+{
+ TcpTracker& trk = static_cast< TcpTracker& >( tracker );
+
+ return default_state_action(tsd, trk, __func__);
+}
+
+bool TcpStateSynSent::fin_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
+{
+ TcpTracker& trk = static_cast< TcpTracker& >( tracker );
+
+ return default_state_action(tsd, trk, __func__);
+}
+
+bool TcpStateSynSent::rst_sent(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
+{
+ TcpTracker& trk = static_cast< TcpTracker& >( tracker );
+
+ return default_state_action(tsd, trk, __func__);
+}
+
+bool TcpStateSynSent::rst_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
+{
+ TcpTracker& trk = static_cast< TcpTracker& >( tracker );
+
+ return default_state_action(tsd, trk, __func__);
+}
+
// tcp_syn_sent_state.h author davis mcpherson <davmcphe@@cisco.com>
// Created on: Aug 5, 2015
-#ifndef TCP_SYN_SENT_STATE_H
-#define TCP_SYN_SENT_STATE_H
+#ifndef TCP_STATE_SYN_SENT_H
+#define TCP_STATE_SYN_SENT_H
#include "stream/libtcp/tcp_state_handler.h"
-class TcpSynSentState: public TcpStateHandler
+class TcpSession;
+
+class TcpStateSynSent : public TcpStateHandler
{
public:
- TcpSynSentState();
- virtual ~TcpSynSentState();
-
- void syn_sent(TcpSegmentDescriptor&, TcpStreamTracker&);
- void syn_recv(TcpSegmentDescriptor&, TcpStreamTracker&);
- void syn_ack_sent(TcpSegmentDescriptor&, TcpStreamTracker&);
- void syn_ack_recv(TcpSegmentDescriptor&, TcpStreamTracker&);
- void ack_sent(TcpSegmentDescriptor&, TcpStreamTracker&);
- void ack_recv(TcpSegmentDescriptor&, TcpStreamTracker&);
- void data_seg_sent(TcpSegmentDescriptor&, TcpStreamTracker&);
- void data_seg_recv(TcpSegmentDescriptor&, TcpStreamTracker&);
- void fin_sent(TcpSegmentDescriptor&, TcpStreamTracker&);
- void fin_recv(TcpSegmentDescriptor&, TcpStreamTracker&);
- void rst_sent(TcpSegmentDescriptor&, TcpStreamTracker&);
- void rst_recv(TcpSegmentDescriptor&, TcpStreamTracker&);
+ TcpStateSynSent(TcpStateMachine&, TcpSession&);
+ virtual ~TcpStateSynSent(void);
+
+ bool syn_sent(TcpSegmentDescriptor&, TcpStreamTracker&) override;
+ bool syn_recv(TcpSegmentDescriptor&, TcpStreamTracker&) override;
+ bool syn_ack_sent(TcpSegmentDescriptor&, TcpStreamTracker&) override;
+ bool syn_ack_recv(TcpSegmentDescriptor&, TcpStreamTracker&) override;
+ bool ack_sent(TcpSegmentDescriptor&, TcpStreamTracker&) override;
+ bool ack_recv(TcpSegmentDescriptor&, TcpStreamTracker&) override;
+ bool data_seg_sent(TcpSegmentDescriptor&, TcpStreamTracker&) override;
+ bool data_seg_recv(TcpSegmentDescriptor&, TcpStreamTracker&) override;
+ bool fin_sent(TcpSegmentDescriptor&, TcpStreamTracker&) override;
+ bool fin_recv(TcpSegmentDescriptor&, TcpStreamTracker&) override;
+ bool rst_sent(TcpSegmentDescriptor&, TcpStreamTracker&) override;
+ bool rst_recv(TcpSegmentDescriptor&, TcpStreamTracker&) override;
+
+private:
+ TcpSession& session;
};
#endif
+
--- /dev/null
+//--------------------------------------------------------------------------
+// Copyright (C) 2015-2015 Cisco and/or its affiliates. All rights reserved.
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License Version 2 as published
+// by the Free Software Foundation. You may not use, modify or distribute
+// this program under any other version of the GNU General Public License.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+//--------------------------------------------------------------------------
+
+// tcp_state_time_wait.cc author davis mcpherson <davmcphe@cisco.com>
+// Created on: Aug 5, 2015
+
+#include <iostream>
+using namespace std;
+
+#include "tcp_module.h"
+#include "tcp_tracker.h"
+#include "tcp_session.h"
+#include "tcp_normalizer.h"
+#include "tcp_state_time_wait.h"
+
+#ifdef UNIT_TEST
+#include "catch/catch.hpp"
+#endif
+
+TcpStateTimeWait::TcpStateTimeWait(TcpStateMachine& tsm, TcpSession& session) :
+ TcpStateHandler(TcpStreamTracker::TCP_TIME_WAIT, tsm), session(session)
+{
+}
+
+TcpStateTimeWait::~TcpStateTimeWait()
+{
+}
+
+bool TcpStateTimeWait::syn_sent(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
+{
+ TcpTracker& trk = static_cast< TcpTracker& >( tracker );
+
+ return default_state_action(tsd, trk, __func__);
+}
+
+bool TcpStateTimeWait::syn_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
+{
+ TcpTracker& trk = static_cast< TcpTracker& >( tracker );
+
+ return default_state_action(tsd, trk, __func__);
+}
+
+bool TcpStateTimeWait::syn_ack_sent(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
+{
+ TcpTracker& trk = static_cast< TcpTracker& >( tracker );
+
+ return default_state_action(tsd, trk, __func__);
+}
+
+bool TcpStateTimeWait::syn_ack_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
+{
+ TcpTracker& trk = static_cast< TcpTracker& >( tracker );
+
+ return default_state_action(tsd, trk, __func__);
+}
+
+bool TcpStateTimeWait::ack_sent(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
+{
+ TcpTracker& trk = static_cast< TcpTracker& >( tracker );
+
+ return default_state_action(tsd, trk, __func__);
+}
+
+bool TcpStateTimeWait::ack_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
+{
+ TcpTracker& trk = static_cast< TcpTracker& >( tracker );
+
+ return default_state_action(tsd, trk, __func__);
+}
+
+bool TcpStateTimeWait::data_seg_sent(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
+{
+ TcpTracker& trk = static_cast< TcpTracker& >( tracker );
+
+ return default_state_action(tsd, trk, __func__);
+}
+
+bool TcpStateTimeWait::data_seg_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
+{
+ TcpTracker& trk = static_cast< TcpTracker& >( tracker );
+
+ return default_state_action(tsd, trk, __func__);
+}
+
+bool TcpStateTimeWait::fin_sent(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
+{
+ TcpTracker& trk = static_cast< TcpTracker& >( tracker );
+
+ return default_state_action(tsd, trk, __func__);
+}
+
+bool TcpStateTimeWait::fin_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
+{
+ TcpTracker& trk = static_cast< TcpTracker& >( tracker );
+
+ return default_state_action(tsd, trk, __func__);
+}
+
+bool TcpStateTimeWait::rst_sent(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
+{
+ TcpTracker& trk = static_cast< TcpTracker& >( tracker );
+
+ return default_state_action(tsd, trk, __func__);
+}
+
+bool TcpStateTimeWait::rst_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
+{
+ TcpTracker& trk = static_cast< TcpTracker& >( tracker );
+
+ return default_state_action(tsd, trk, __func__);
+}
+
--- /dev/null
+//--------------------------------------------------------------------------
+// Copyright (C) 2015-2015 Cisco and/or its affiliates. All rights reserved.
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License Version 2 as published
+// by the Free Software Foundation. You may not use, modify or distribute
+// this program under any other version of the GNU General Public License.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+//--------------------------------------------------------------------------
+
+// tcp_state_time_wait.h author davis mcpherson <davmcphe@@cisco.com>
+// Created on: Aug 5, 2015
+
+#ifndef TCP_STATE_TIME_WAIT_H
+#define TCP_STATE_TIME_WAIT_H
+
+#include "stream/libtcp/tcp_state_handler.h"
+
+class TcpSession;
+
+class TcpStateTimeWait : public TcpStateHandler
+{
+public:
+ TcpStateTimeWait(TcpStateMachine&, TcpSession&);
+ virtual ~TcpStateTimeWait(void);
+
+ bool syn_sent(TcpSegmentDescriptor&, TcpStreamTracker&) override;
+ bool syn_recv(TcpSegmentDescriptor&, TcpStreamTracker&) override;
+ bool syn_ack_sent(TcpSegmentDescriptor&, TcpStreamTracker&) override;
+ bool syn_ack_recv(TcpSegmentDescriptor&, TcpStreamTracker&) override;
+ bool ack_sent(TcpSegmentDescriptor&, TcpStreamTracker&) override;
+ bool ack_recv(TcpSegmentDescriptor&, TcpStreamTracker&) override;
+ bool data_seg_sent(TcpSegmentDescriptor&, TcpStreamTracker&) override;
+ bool data_seg_recv(TcpSegmentDescriptor&, TcpStreamTracker&) override;
+ bool fin_sent(TcpSegmentDescriptor&, TcpStreamTracker&) override;
+ bool fin_recv(TcpSegmentDescriptor&, TcpStreamTracker&) override;
+ bool rst_sent(TcpSegmentDescriptor&, TcpStreamTracker&) override;
+ bool rst_recv(TcpSegmentDescriptor&, TcpStreamTracker&) override;
+
+private:
+ TcpSession& session;
+};
+
+#endif
+
--- /dev/null
+//--------------------------------------------------------------------------
+// Copyright (C) 2015-2015 Cisco and/or its affiliates. All rights reserved.
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License Version 2 as published
+// by the Free Software Foundation. You may not use, modify or distribute
+// this program under any other version of the GNU General Public License.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+//--------------------------------------------------------------------------
+
+// tcp_stream_config.cc author davis mcpherson <davmcphe@@cisco.com>
+// Created on: Oct 22, 2015
+
+#include "main/snort_config.h"
+#include "time/packet_time.h"
+#include "stream/stream.h"
+#include "tcp_stream_config.h"
+
+static const char* const reassembly_policy_names[] = { "no policy", "first",
+ "last", "linux", "old_linux", "bsd",
+ "macos", "solaris", "irix",
+ "hpux11", "hpux10", "windows", "win_2003",
+ "vista", "proxy" };
+
+TcpStreamConfig::TcpStreamConfig(void)
+{
+ policy = StreamPolicy::OS_DEFAULT;
+ reassembly_policy = ReassemblyPolicy::OS_DEFAULT;
+
+ flags = 0;
+ flush_factor = 0;
+
+ session_timeout = STREAM_DEFAULT_SSN_TIMEOUT;
+ max_window = 0;
+ overlap_limit = 0;
+
+ max_queued_bytes = STREAM_DEFAULT_MAX_QUEUED_BYTES;
+ max_queued_segs = STREAM_DEFAULT_MAX_QUEUED_SEGS;
+
+ max_consec_small_segs = STREAM_DEFAULT_CONSEC_SMALL_SEGS;
+ max_consec_small_seg_size = STREAM_DEFAULT_MAX_SMALL_SEG_SIZE;
+
+ hs_timeout = -1;
+ footprint = 0;
+ paf_max = 16384;
+}
+
+bool TcpStreamConfig::require_3whs(void)
+{
+ return hs_timeout >= 0;
+}
+
+bool TcpStreamConfig::midstream_allowed(Packet* p)
+{
+ if ( ( hs_timeout < 0 ) || ( p->pkth->ts.tv_sec - packet_first_time() < hs_timeout ) )
+ return true;
+
+ return false;
+}
+
+void TcpStreamConfig::show_config(void)
+{
+ TcpStreamConfig::show_config(this);
+}
+
+void TcpStreamConfig::show_config(TcpStreamConfig* config)
+{
+ LogMessage("Stream TCP Policy config:\n");
+ LogMessage(" Reassembly Policy: %s\n",
+ reassembly_policy_names[ static_cast<int>( config->reassembly_policy ) ]);
+ LogMessage(" Timeout: %d seconds\n", config->session_timeout);
+
+ if ( config->max_window != 0 )
+ LogMessage(" Max TCP Window: %u\n", config->max_window);
+
+ if ( config->overlap_limit )
+ LogMessage(" Limit on TCP Overlaps: %d\n", config->overlap_limit);
+
+ if ( config->max_queued_bytes != 0 )
+ LogMessage(" Maximum number of bytes to queue per session: %d\n",
+ config->max_queued_bytes);
+
+ if ( config->max_queued_segs != 0 )
+ LogMessage(" Maximum number of segs to queue per session: %d\n",
+ config->max_queued_segs);
+
+ if ( config->flags )
+ {
+ LogMessage(" Options:\n");
+ if (config->flags & STREAM_CONFIG_IGNORE_ANY)
+ LogMessage(" Ignore Any -> Any Rules: YES\n");
+
+ if (config->flags & STREAM_CONFIG_NO_ASYNC_REASSEMBLY)
+ LogMessage(" Don't queue packets on one-sided sessions: YES\n");
+ }
+
+ if ( config->hs_timeout < 0 )
+ LogMessage(" Require 3-Way Handshake: NO\n");
+ else
+ LogMessage(" Require 3-Way Handshake: after %d seconds\n", config->hs_timeout);
+}
+
+//-------------------------------------------------------------------------
+// attribute table foo
+//-------------------------------------------------------------------------
+
+int TcpStreamConfig::verify_config(SnortConfig*)
+{
+ return 0;
+}
+
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
//--------------------------------------------------------------------------
-// tcp_listen_state.h author davis mcpherson <davmcphe@cisco.com>
-// Created on: Jul 30, 2015
+// tcp_stream_config.h author davis mcpherson <davmcphe@@cisco.com>
+// Created on: Oct 22, 2015
-#ifndef TCP_LISTEN_STATE_H
-#define TCP_LISTEN_STATE_H
+#ifndef TCP_STREAM_CONFIG_H
+#define TCP_STREAM_CONFIG_H
-#include "stream/libtcp/tcp_state_handler.h"
+#include "tcp_defs.h"
-class TcpListenState: public TcpStateHandler
+class TcpStreamConfig
{
public:
- TcpListenState();
- virtual ~TcpListenState();
+ TcpStreamConfig(void);
+ bool require_3whs(void);
+ bool midstream_allowed(Packet*);
+ int verify_config(SnortConfig*);
+ void show_config(void);
+ static void show_config(TcpStreamConfig*);
+
+ StreamPolicy policy;
+ ReassemblyPolicy reassembly_policy;
+
+ uint16_t flags;
+ uint16_t flush_factor;
+
+ uint32_t session_timeout;
+ uint32_t max_window;
+ uint32_t overlap_limit;
+
+ uint32_t max_queued_bytes;
+ uint32_t max_queued_segs;
+
+ uint32_t max_consec_small_segs;
+ uint32_t max_consec_small_seg_size;
+
+ int hs_timeout;
+ int footprint;
+ unsigned paf_max;
};
#endif
+
+++ /dev/null
-//--------------------------------------------------------------------------
-// Copyright (C) 2015-2015 Cisco and/or its affiliates. All rights reserved.
-//
-// This program is free software; you can redistribute it and/or modify it
-// under the terms of the GNU General Public License Version 2 as published
-// by the Free Software Foundation. You may not use, modify or distribute
-// this program under any other version of the GNU General Public License.
-//
-// This program is distributed in the hope that it will be useful, but
-// WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-// General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License along
-// with this program; if not, write to the Free Software Foundation, Inc.,
-// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
-//--------------------------------------------------------------------------
-
-// tcp_syn_sent_state.cc author davis mcpherson <davmcphe@@cisco.com>
-// Created on: Aug 5, 2015
-
-#include <iostream>
-using namespace std;
-
-#include "tcp_syn_recv_state.h"
-
-TcpSynRecvState::TcpSynRecvState()
-{
- // TODO Auto-generated constructor stub
-
-}
-
-TcpSynRecvState::~TcpSynRecvState()
-{
- // TODO Auto-generated destructor stub
-}
-
-void TcpSynRecvState::syn_sent( TcpSegmentDescriptor &tcp_seg, TcpStreamTracker &tracker )
-{
- default_state_action( &tcp_seg, &tracker, __func__ );
-}
-
-void TcpSynRecvState::syn_recv(TcpSegmentDescriptor &tcp_seg, TcpStreamTracker &tracker)
-{
- default_state_action( &tcp_seg, &tracker, __func__ );
-}
-
-void TcpSynRecvState::syn_ack_sent(TcpSegmentDescriptor &tcp_seg, TcpStreamTracker &tracker)
-{
- default_state_action( &tcp_seg, &tracker, __func__ );
-}
-
-void TcpSynRecvState::syn_ack_recv(TcpSegmentDescriptor &tcp_seg, TcpStreamTracker &tracker)
-{
- default_state_action( &tcp_seg, &tracker, __func__ );
-}
-
-void TcpSynRecvState::ack_sent(TcpSegmentDescriptor &tcp_seg, TcpStreamTracker &tracker)
-{
- default_state_action( &tcp_seg, &tracker, __func__ );
-}
-
-void TcpSynRecvState::ack_recv(TcpSegmentDescriptor &tcp_seg, TcpStreamTracker &tracker)
-{
- default_state_action( &tcp_seg, &tracker, __func__ );
-}
-
-void TcpSynRecvState::data_seg_sent(TcpSegmentDescriptor &tcp_seg, TcpStreamTracker &tracker)
-{
- default_state_action( &tcp_seg, &tracker, __func__ );
-}
-
-void TcpSynRecvState::data_seg_recv(TcpSegmentDescriptor &tcp_seg, TcpStreamTracker &tracker)
-{
- default_state_action( &tcp_seg, &tracker, __func__ );
-}
-
-void TcpSynRecvState::fin_sent(TcpSegmentDescriptor &tcp_seg, TcpStreamTracker &tracker)
-{
- default_state_action( &tcp_seg, &tracker, __func__ );
-}
-
-void TcpSynRecvState::fin_recv(TcpSegmentDescriptor &tcp_seg, TcpStreamTracker &tracker)
-{
- default_state_action( &tcp_seg, &tracker, __func__ );
-}
-
-void TcpSynRecvState::rst_sent(TcpSegmentDescriptor &tcp_seg, TcpStreamTracker &tracker)
-{
- default_state_action( &tcp_seg, &tracker, __func__ );
-}
-
-void TcpSynRecvState::rst_recv(TcpSegmentDescriptor &tcp_seg, TcpStreamTracker &tracker)
-{
- default_state_action( &tcp_seg, &tracker, __func__ );
-}
-
+++ /dev/null
-//--------------------------------------------------------------------------
-// Copyright (C) 2015-2015 Cisco and/or its affiliates. All rights reserved.
-//
-// This program is free software; you can redistribute it and/or modify it
-// under the terms of the GNU General Public License Version 2 as published
-// by the Free Software Foundation. You may not use, modify or distribute
-// this program under any other version of the GNU General Public License.
-//
-// This program is distributed in the hope that it will be useful, but
-// WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-// General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License along
-// with this program; if not, write to the Free Software Foundation, Inc.,
-// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
-//--------------------------------------------------------------------------
-
-// tcp_syn_sent_state.cc author davis mcpherson <davmcphe@@cisco.com>
-// Created on: Aug 5, 2015
-
-#include <iostream>
-using namespace std;
-
-#include "tcp_syn_sent_state.h"
-
-#ifdef UNIT_TEST
-#include "catch/catch.hpp"
-#endif
-
-TcpSynSentState::TcpSynSentState()
-{
- // TODO Auto-generated constructor stub
-
-}
-
-TcpSynSentState::~TcpSynSentState()
-{
- // TODO Auto-generated destructor stub
-}
-
-void TcpSynSentState::syn_sent( TcpSegmentDescriptor &tcp_seg, TcpStreamTracker &tracker )
-{
- default_state_action( &tcp_seg, &tracker, __func__ );
-}
-
-void TcpSynSentState::syn_recv(TcpSegmentDescriptor &tcp_seg, TcpStreamTracker &tracker)
-{
- default_state_action( &tcp_seg, &tracker, __func__ );
-}
-
-void TcpSynSentState::syn_ack_sent(TcpSegmentDescriptor &tcp_seg, TcpStreamTracker &tracker)
-{
- default_state_action( &tcp_seg, &tracker, __func__ );
-}
-
-void TcpSynSentState::syn_ack_recv(TcpSegmentDescriptor &tcp_seg, TcpStreamTracker &tracker)
-{
- default_state_action( &tcp_seg, &tracker, __func__ );
-}
-
-void TcpSynSentState::ack_sent(TcpSegmentDescriptor &tcp_seg, TcpStreamTracker &tracker)
-{
- default_state_action( &tcp_seg, &tracker, __func__ );
-}
-
-void TcpSynSentState::ack_recv(TcpSegmentDescriptor &tcp_seg, TcpStreamTracker &tracker)
-{
- default_state_action( &tcp_seg, &tracker, __func__ );
-}
-
-void TcpSynSentState::data_seg_sent(TcpSegmentDescriptor &tcp_seg, TcpStreamTracker &tracker)
-{
- default_state_action( &tcp_seg, &tracker, __func__ );
-}
-
-void TcpSynSentState::data_seg_recv(TcpSegmentDescriptor &tcp_seg, TcpStreamTracker &tracker)
-{
- default_state_action( &tcp_seg, &tracker, __func__ );
-}
-
-void TcpSynSentState::fin_sent(TcpSegmentDescriptor &tcp_seg, TcpStreamTracker &tracker)
-{
- default_state_action( &tcp_seg, &tracker, __func__ );
-}
-
-void TcpSynSentState::fin_recv(TcpSegmentDescriptor &tcp_seg, TcpStreamTracker &tracker)
-{
- default_state_action( &tcp_seg, &tracker, __func__ );
-}
-
-void TcpSynSentState::rst_sent(TcpSegmentDescriptor &tcp_seg, TcpStreamTracker &tracker)
-{
- default_state_action( &tcp_seg, &tracker, __func__ );
-}
-
-void TcpSynSentState::rst_recv(TcpSegmentDescriptor &tcp_seg, TcpStreamTracker &tracker)
-{
- default_state_action( &tcp_seg, &tracker, __func__ );
-}
-
-#ifdef UNIT_TEST
-
-#endif
--- /dev/null
+//--------------------------------------------------------------------------
+// Copyright (C) 2015-2015 Cisco and/or its affiliates. All rights reserved.
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License Version 2 as published
+// by the Free Software Foundation. You may not use, modify or distribute
+// this program under any other version of the GNU General Public License.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+//--------------------------------------------------------------------------
+
+// tcp_tracker.cc author davis mcpherson <davmcphe@@cisco.com>
+// Created on: Dec 1, 2015
+
+#include "profiler/profiler_defs.h"
+#include "tcp_module.h"
+#include "tcp_normalizers.h"
+#include "tcp_reassemblers.h"
+#include "tcp_tracker.h"
+
+TcpTracker::TcpTracker(bool client) :
+ TcpStreamTracker(client), splitter(nullptr), normalizer(nullptr), reassembler(nullptr)
+{
+ tcp_event = TCP_MAX_EVENTS;
+ init_tracker( );
+}
+
+TcpTracker::~TcpTracker(void)
+{
+ delete splitter;
+ delete normalizer;
+ delete reassembler;
+}
+
+void TcpTracker::init_tracker(void)
+{
+ memset(&s_mgr, 0, sizeof( StateMgr ) );
+ s_mgr.state_queue = TcpStreamTracker::TCP_STATE_NONE;
+
+ tcp_state = TcpStreamTracker::TCP_STATE_NONE;
+ flush_policy = STREAM_FLPOLICY_IGNORE;
+ memset(&paf_state, 0, sizeof( PAF_State ) );
+ snd_una = snd_nxt = snd_wnd = 0;
+ r_nxt_ack = r_win_base = iss = ts_last = ts_last_packet = 0;
+ small_seg_count = wscale = mss = 0;
+ memset(mac_addr, 0, 6);
+ flags = 0;
+ alert_count = 0;
+ memset(alerts, 0, sizeof( alerts ) );
+
+ delete splitter;
+ splitter = nullptr;
+ delete normalizer;
+ normalizer = nullptr;
+ delete reassembler;
+ reassembler = nullptr;
+}
+
+//-------------------------------------------------------------------------
+// flush policy stuff
+//-------------------------------------------------------------------------
+
+void TcpTracker::init_flush_policy(void)
+{
+ if ( splitter == nullptr )
+ flush_policy = STREAM_FLPOLICY_IGNORE;
+ else if ( !normalizer->is_tcp_ips_enabled() )
+ flush_policy = STREAM_FLPOLICY_ON_ACK;
+ else
+ flush_policy = STREAM_FLPOLICY_ON_DATA;
+}
+
+void TcpTracker::set_splitter(StreamSplitter* ss)
+{
+ if ( splitter )
+ delete splitter;
+
+ splitter = ss;
+
+ if ( ss )
+ paf_setup(&paf_state);
+ else
+ flush_policy = STREAM_FLPOLICY_IGNORE;
+}
+
+void TcpTracker::set_splitter(const Flow* flow)
+{
+ Inspector* ins = flow->gadget;
+
+ if ( !ins )
+ ins = flow->clouseau;
+
+ if ( ins )
+ set_splitter(ins->get_splitter(!client_tracker) );
+ else
+ set_splitter(new AtomSplitter(!client_tracker) );
+}
+
+void TcpTracker::init_on_syn_sent(TcpSegmentDescriptor& tsd)
+{
+ Profile profile(s5TcpNewSessPerfStats);
+
+ tsd.get_flow()->set_session_flags(SSNFLAG_SEEN_CLIENT);
+ if ( tsd.get_tcph()->are_flags_set(TH_CWR | TH_ECE) )
+ tsd.get_flow()->set_session_flags(SSNFLAG_ECN_CLIENT_QUERY);
+
+ iss = tsd.get_seq();
+ snd_una = tsd.get_seq() + 1;
+ if ( tsd.get_seq() == tsd.get_end_seq() )
+ snd_nxt = snd_una;
+ else
+ snd_nxt = snd_una + ( tsd.get_end_seq() - tsd.get_seq() - 1 );
+
+ snd_wnd = tsd.get_win();
+ ts_last_packet = tsd.get_pkt()->pkth->ts.tv_sec;
+
+ flags |= normalizer->get_tcp_timestamp(tsd, false);
+ ts_last = tsd.get_ts();
+ if (ts_last == 0)
+ flags |= TF_TSTAMP_ZERO;
+ flags |= tsd.init_mss(&mss);
+ flags |= tsd.init_wscale(&wscale);
+
+ cache_mac_address(tsd, FROM_CLIENT);
+ set_splitter(tsd.get_flow() );
+ init_flush_policy( );
+
+ tcp_state = TcpStreamTracker::TCP_SYN_SENT;
+}
+
+void TcpTracker::init_on_syn_recv(TcpSegmentDescriptor& tsd)
+{
+ Profile profile(s5TcpNewSessPerfStats);
+
+ reassembler->set_seglist_base_seq(tsd.get_seq() + 1);
+ r_nxt_ack = tsd.get_seq() + 1;
+ r_win_base = tsd.get_seq() + 1;
+
+ cache_mac_address(tsd, FROM_CLIENT);
+ set_splitter(tsd.get_flow() );
+ init_flush_policy( );
+
+ tcp_state = TcpStreamTracker::TCP_LISTEN;
+}
+
+void TcpTracker::init_on_synack_sent(TcpSegmentDescriptor& tsd)
+{
+ Profile profile(s5TcpNewSessPerfStats);
+
+ DebugMessage(DEBUG_STREAM_STATE, "Creating new session tracker on SYN_ACK!\n");
+
+ tsd.get_flow()->set_session_flags(SSNFLAG_SEEN_SERVER);
+ if (tsd.get_tcph()->are_flags_set(TH_CWR | TH_ECE))
+ tsd.get_flow()->set_session_flags(SSNFLAG_ECN_SERVER_REPLY);
+
+ iss =tsd.get_seq();
+ snd_una = tsd.get_seq() + 1;
+ snd_nxt = snd_una;
+ snd_wnd = tsd.get_win();
+
+ reassembler->set_seglist_base_seq(tsd.get_ack() );
+ r_win_base = tsd.get_ack();
+ r_nxt_ack = tsd.get_ack();
+ ts_last_packet = tsd.get_pkt()->pkth->ts.tv_sec;
+
+ flags |= normalizer->get_tcp_timestamp(tsd, false);
+ ts_last = tsd.get_ts();
+ if ( ts_last == 0 )
+ flags |= TF_TSTAMP_ZERO;
+ flags |= tsd.init_mss(&mss);
+ flags |= tsd.init_wscale(&wscale);
+
+ cache_mac_address(tsd, FROM_SERVER);
+ set_splitter(tsd.get_flow() );
+ init_flush_policy();
+
+ tcp_state = TcpStreamTracker::TCP_SYN_RECV;
+}
+
+void TcpTracker::init_on_synack_recv(TcpSegmentDescriptor& tsd)
+{
+ Profile profile(s5TcpNewSessPerfStats);
+
+ reassembler->set_seglist_base_seq(tsd.get_seq() + 1);
+ iss = tsd.get_ack() - 1;
+ r_nxt_ack = tsd.get_seq() + 1;
+ r_win_base = tsd.get_seq() + 1;
+ snd_nxt = tsd.get_ack();
+
+ cache_mac_address(tsd, FROM_SERVER);
+ set_splitter(tsd.get_flow() );
+ init_flush_policy();
+
+ tcp_state = TcpStreamTracker::TCP_SYN_SENT;
+}
+
+void TcpTracker::init_on_3whs_ack_sent(TcpSegmentDescriptor& tsd)
+{
+ Profile profile(s5TcpNewSessPerfStats);
+
+ tsd.get_flow()->set_session_flags(SSNFLAG_SEEN_CLIENT);
+
+ if ( tsd.get_tcph()->are_flags_set(TH_CWR | TH_ECE) )
+ tsd.get_flow()->set_session_flags(SSNFLAG_ECN_CLIENT_QUERY);
+
+ iss = tsd.get_seq();
+ snd_una = tsd.get_seq() + 1;
+ snd_nxt = tsd.get_seq() + 1;
+ snd_wnd = tsd.get_win();
+ ts_last_packet = tsd.get_pkt()->pkth->ts.tv_sec;
+ flags |= normalizer->get_tcp_timestamp(tsd, false);
+ ts_last = tsd.get_ts();
+ if (ts_last == 0)
+ flags |= TF_TSTAMP_ZERO;
+ flags |= tsd.init_mss(&mss);
+ flags |= tsd.init_wscale(&wscale);
+
+ cache_mac_address(tsd, FROM_CLIENT);
+ set_splitter(tsd.get_flow() );
+ init_flush_policy();
+ tcp_state = TcpStreamTracker::TCP_ESTABLISHED;
+}
+
+void TcpTracker::init_on_3whs_ack_recv(TcpSegmentDescriptor& tsd)
+{
+ Profile profile(s5TcpNewSessPerfStats);
+
+ reassembler->set_seglist_base_seq(tsd.get_seq() + 1);
+ r_nxt_ack = tsd.get_seq() + 1;
+ r_win_base = tsd.get_seq() + 1;
+
+ cache_mac_address(tsd, FROM_CLIENT);
+ set_splitter(tsd.get_flow() );
+ init_flush_policy();
+ tcp_state = TcpStreamTracker::TCP_ESTABLISHED;
+}
+
+void TcpTracker::init_on_data_seg_sent(TcpSegmentDescriptor& tsd)
+{
+ Profile profile(s5TcpNewSessPerfStats);
+
+ iss = tsd.get_seq();
+ snd_una = tsd.get_seq();
+ snd_nxt = tsd.get_seq();
+ snd_wnd = tsd.get_win();
+ if ( tsd.get_direction() == FROM_SERVER )
+ {
+ r_win_base = tsd.get_ack();
+ r_nxt_ack = tsd.get_ack();
+ reassembler->set_seglist_base_seq(tsd.get_ack() );
+ }
+ else
+ {
+ r_win_base = 0;
+ r_nxt_ack = 0;
+ }
+
+ ts_last_packet = tsd.get_pkt()->pkth->ts.tv_sec;
+ flags |= normalizer->get_tcp_timestamp(tsd, 0);
+ ts_last = tsd.get_ts();
+ if (ts_last == 0)
+ flags |= TF_TSTAMP_ZERO;
+ flags |= tsd.init_mss(&mss);
+ flags |= tsd.init_wscale(&wscale);
+
+ cache_mac_address(tsd, tsd.get_direction() );
+ set_splitter(tsd.get_flow() );
+ init_flush_policy();
+ tcp_state = TcpStreamTracker::TCP_ESTABLISHED;
+}
+
+void TcpTracker::init_on_data_seg_recv(TcpSegmentDescriptor& tsd)
+{
+ Profile profile(s5TcpNewSessPerfStats);
+
+ if ( tsd.get_direction() == FROM_SERVER )
+ iss = tsd.get_ack() - 1;
+ else
+ snd_una = tsd.get_ack() - 1;
+
+ r_nxt_ack = tsd.get_seq();
+ r_win_base = tsd.get_seq();
+ snd_wnd = 0; /* reset later */
+ reassembler->set_seglist_base_seq(tsd.get_seq() );
+
+ cache_mac_address(tsd, tsd.get_direction() );
+ set_splitter(tsd.get_flow() );
+ init_flush_policy();
+ tcp_state = TcpStreamTracker::TCP_ESTABLISHED;
+}
+
+void TcpTracker::print(void)
+{
+ LogMessage(" + TcpTracker +\n");
+ LogMessage(" state: %s\n", tcp_state_names[ tcp_state ]);
+ LogMessage(" state_queue: %s\n", tcp_state_names[ s_mgr.state_queue ]);
+ LogMessage(" expected_flags: 0x%X\n", s_mgr.expected_flags);
+ LogMessage(" transition_seq: 0x%X\n", s_mgr.transition_seq);
+ LogMessage(" stq_get_seq: %d\n", s_mgr.stq_get_seq);
+ LogMessage(" iss: 0x%X\n", iss);
+ LogMessage(" ts_last: %u\n", ts_last);
+ LogMessage(" wscale: %u\n", wscale);
+ LogMessage(" mss: 0x%08X\n", mss);
+ LogMessage(" snd_una: %X\n", snd_una);
+ LogMessage(" snd_nxt: %X\n", snd_nxt);
+ LogMessage(" snd_win: %u\n", snd_wnd);
+ LogMessage(" rcv_nxt: %X\n", rcv_nxt);
+ LogMessage(" r_win_base: %X\n", r_win_base);
+}
+
--- /dev/null
+//--------------------------------------------------------------------------
+// Copyright (C) 2015-2015 Cisco and/or its affiliates. All rights reserved.
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License Version 2 as published
+// by the Free Software Foundation. You may not use, modify or distribute
+// this program under any other version of the GNU General Public License.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+//--------------------------------------------------------------------------
+
+// tcp_tracker.h author davis mcpherson <davmcphe@@cisco.com>
+// Created on: Dec 1, 2015
+
+#ifndef TCP_TRACKER_H_
+#define TCP_TRACKER_H_
+
+#include "stream/libtcp/tcp_stream_tracker.h"
+#include "stream/paf.h"
+#include "tcp_defs.h"
+
+struct StateMgr
+{
+ uint8_t sub_state;
+ enum TcpStreamTracker::TcpStates state_queue;
+ uint8_t expected_flags;
+ uint32_t transition_seq;
+ uint32_t stq_get_seq;
+};
+
+//-------------------------------------------------------------------------
+// extra, extra - read all about it!
+// -- u2 is the only output plugin that currently supports extra data
+// -- extra data may be captured before or after alerts
+// -- extra data may be per packet or persistent (saved on session)
+//
+// -- per packet extra data is logged iff we alert on the packet
+// containing the extra data - u2 drives this
+// -- an extra data mask is added to Packet to indicate when per packet
+// extra data is available
+//
+// -- persistent extra data must be logged exactly once for each alert
+// regardless of capture/alert ordering - s5 purge_alerts drives this
+// -- an extra data mask is added to the session trackers to indicate that
+// persistent extra data is available
+//
+// -- event id and second are added to the session alert trackers so that
+// the extra data can be correlated with events
+// -- event id and second are not available when check_alerted()
+// is called; u2 calls StreamUpdateSessionAlertTcp as events are logged
+// to set these fields
+//-------------------------------------------------------------------------
+
+/* Only track a maximum number of alerts per session */
+#define MAX_SESSION_ALERTS 8
+struct StreamAlertInfo
+{
+ /* For storing alerts that have already been seen on the session */
+ uint32_t sid;
+ uint32_t gid;
+ uint32_t seq;
+ // if we log extra data, event_* is used to correlate with alert
+ uint32_t event_id;
+ uint32_t event_second;
+};
+
+class TcpNormalizer;
+class TcpReassembler;
+
+class TcpTracker : public TcpStreamTracker
+{
+public:
+ TcpTracker(bool);
+ virtual ~TcpTracker(void);
+ void init_tracker(void);
+ void print(void);
+ void init_flush_policy(void);
+ void set_splitter(StreamSplitter* ss);
+ void set_splitter(const Flow* flow);
+
+ void init_on_syn_sent(TcpSegmentDescriptor&);
+ void init_on_syn_recv(TcpSegmentDescriptor&);
+ void init_on_synack_sent(TcpSegmentDescriptor& tsd);
+ void init_on_synack_recv(TcpSegmentDescriptor& tsd);
+ void init_on_3whs_ack_sent(TcpSegmentDescriptor& tsd);
+ void init_on_3whs_ack_recv(TcpSegmentDescriptor& tsd);
+ void init_on_data_seg_sent(TcpSegmentDescriptor& tsd);
+ void init_on_data_seg_recv(TcpSegmentDescriptor& tsd);
+
+ StateMgr s_mgr; /* state tracking goodies */
+
+ // this is intended to be private to paf but is included
+ // directly to avoid the need for allocation; do not directly
+ // manipulate within this module.
+ PAF_State paf_state; // for tracking protocol aware flushing
+ FlushPolicy flush_policy;
+ StreamSplitter* splitter;
+ TcpNormalizer* normalizer;
+ TcpReassembler* reassembler;
+
+ uint32_t r_nxt_ack; /* next expected ack from remote side */
+ uint32_t r_win_base; /* remote side window base sequence number
+ * (i.e. the last ack we got) */
+
+ uint32_t small_seg_count;
+
+ uint8_t alert_count; /* number alerts stored (up to MAX_SESSION_ALERTS) */
+ StreamAlertInfo alerts[MAX_SESSION_ALERTS]; /* history of alerts */
+};
+
+#endif
+