]> git.ipfire.org Git - thirdparty/snort3.git/commitdiff
catch unit test updates, making libtcp real
authordavis mcpherson <davmcphe@cisco.com>
Mon, 31 Aug 2015 15:01:55 +0000 (15:01 +0000)
committerdavis mcpherson <davmcphe@cisco.com>
Tue, 1 Sep 2015 17:26:12 +0000 (17:26 +0000)
24 files changed:
src/CMakeLists.txt
src/Makefile.am
src/protocols/tcp.h
src/stream/libtcp/CMakeLists.txt
src/stream/libtcp/Makefile.am
src/stream/libtcp/dev_notes.txt [new file with mode: 0644]
src/stream/libtcp/stream_tcp_unit_test.cc [new file with mode: 0644]
src/stream/libtcp/stream_tcp_unit_test.h [new file with mode: 0644]
src/stream/libtcp/tcp_segment_descriptor.cc
src/stream/libtcp/tcp_segment_descriptor.h
src/stream/libtcp/tcp_state_handler.cc
src/stream/libtcp/tcp_state_handler.h
src/stream/libtcp/tcp_state_machine.cc
src/stream/libtcp/tcp_state_machine.h
src/stream/libtcp/tcp_stream_tracker.cc
src/stream/libtcp/tcp_stream_tracker.h
src/stream/tcp/CMakeLists.txt
src/stream/tcp/Makefile.am
src/stream/tcp/ips_stream_reassemble.cc
src/stream/tcp/ips_stream_size.cc
src/stream/tcp/tcp_closed_state.cc [new file with mode: 0644]
src/stream/tcp/tcp_closed_state.h [new file with mode: 0644]
src/stream/tcp/tcp_session.cc
src/stream/tcp/tcp_syn_sent_state.cc

index df1b7a1849033e96a0833277076ea064b0eec8e8..64415a7572910e7e3f655fc331db7f71cfa8b8d7 100644 (file)
@@ -98,8 +98,8 @@ target_link_libraries( snort
     stream_base
     stream_ip
     stream_icmp
-    stream_libtcp
     stream_tcp
+    stream_libtcp
     stream_udp
     stream_user
     stream_file
index 5396e6fcc6f3540b846fd69bff5f56d9914b9fdb..2076e0e66a557df12929a91c8549402fc6b38045 100644 (file)
@@ -60,8 +60,8 @@ stream/libstream.a \
 stream/base/libstream_base.a \
 stream/ip/libstream_ip.a \
 stream/icmp/libstream_icmp.a \
-stream/libtcp/libstream_libtcp.a \
 stream/tcp/libstream_tcp.a \
+stream/libtcp/libstream_libtcp.a \
 stream/udp/libstream_udp.a \
 stream/user/libstream_user.a \
 stream/file/libstream_file.a \
index ef38ae7fc08808dc28e858a6dea0ab17c73944d2..1fff8337f5ad1f05385fb5c8fcd9da0bab6dab39 100644 (file)
@@ -130,6 +130,9 @@ struct TCPHdr
     inline bool is_rst() const
     { return (th_flags & TH_RST); }
 
+    inline bool is_fin() const
+       { return (th_flags & TH_FIN); }
+
     /*  raw data access */
     inline uint16_t raw_src_port() const
     { return th_sport; }
index 767ddcc83c5ba7ff9ec0d3a65974ac4af17d0059..c992491cdcbff0029a40367f38821e30acee9ac3 100644 (file)
@@ -1,6 +1,8 @@
 
 add_library( stream_libtcp STATIC
-       tcp_stream_tracker.cc
+       tcp_segment_descriptor.cc
+    tcp_stream_tracker.cc
        tcp_state_handler.cc
        tcp_state_machine.cc
+       stream_tcp_unit_test.cc
 )
index a00832b459b95c8a5eb7be69e920adaa576c332b..aadeb44fad76efea7f773a52e4e6f63fa0458f73 100644 (file)
@@ -9,4 +9,7 @@ tcp_stream_tracker.h \
 tcp_state_handler.cc \
 tcp_state_handler.h \
 tcp_state_machine.cc \
-tcp_state_machine.h
+tcp_state_machine.h \
+tcp_segment_descriptor.cc \
+tcp_segment_descriptor.h \
+stream_tcp_unit_test.cc
diff --git a/src/stream/libtcp/dev_notes.txt b/src/stream/libtcp/dev_notes.txt
new file mode 100644 (file)
index 0000000..12a79d0
--- /dev/null
@@ -0,0 +1,18 @@
+This directory contains the implementation of common TCP session tracking functions.
+
+This TCP library module provides the following functions:
+
+* TCP Segment Descriptor - this class provides access to the various fields of the TCP
+  header and payload
+
+* TCP Stream Tracker - this class encapsulates all the state information required for
+  tracking one side of the TCP connection.  For each flow that is tracked there will be
+  two instances of this tracker, one for each direction.
+
+* TCP State Handler - abstract class interface that defines a method for handling each
+  possible TCP event.  For each TCP state a subclass of this class is created with a
+  state specific implementation for each event handling method.
+
+* TCP State Machine - this class is the engine that dispatches processing to the correct
+  event handling method of the handler for the current TCP state of the flow.
+
diff --git a/src/stream/libtcp/stream_tcp_unit_test.cc b/src/stream/libtcp/stream_tcp_unit_test.cc
new file mode 100644 (file)
index 0000000..39faf99
--- /dev/null
@@ -0,0 +1,134 @@
+//--------------------------------------------------------------------------
+// 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.
+//--------------------------------------------------------------------------
+
+// stream_libtcp_unit_test.h author davis mcpherson <davmcphe@@cisco.com>
+// Created on: Jul 30, 2015
+
+#ifndef STREAM_LIBTCP_UNIT_TEST
+#define STREAM_LIBTCP_UNIT_TEST
+
+#include <stdint.h>
+
+#include "protocols/packet.h"
+#include "protocols/tcp.h"
+#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";
+
+// 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";
+
+// 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";
+
+// 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";
+
+// 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";
+
+// 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";
+
+
+Packet *get_syn_packet( Flow* flow )
+{
+       Packet* pkt = new Packet;
+
+       pkt->flow = flow;
+       pkt->pkt = cooked_syn;
+       pkt->ptrs.tcph = ( tcp::TCPHdr * ) ( cooked_syn + 34 );
+       pkt->dsize = 0;
+       pkt->packet_flags &= PKT_FROM_CLIENT;
+       return pkt;
+
+}
+
+Packet *get_syn_ack_packet( Flow* flow )
+{
+       Packet* pkt = new Packet;
+
+       pkt->flow = flow;
+       pkt->pkt = cooked_syn_ack;
+       pkt->ptrs.tcph = ( tcp::TCPHdr * ) ( cooked_syn_ack + 34 );
+       pkt->dsize = 0;
+       pkt->packet_flags &= PKT_FROM_SERVER;
+       return pkt;
+
+}
+
+Packet *get_ack_packet( Flow* flow )
+{
+       Packet* pkt = new Packet;
+
+       pkt->flow = flow;
+       pkt->pkt = cooked_ack;
+       pkt->ptrs.tcph = ( tcp::TCPHdr * ) ( cooked_ack + 34 );
+       pkt->dsize = 0;
+       pkt->packet_flags &= PKT_FROM_CLIENT;
+       return pkt;
+
+}
+
+Packet *get_fin_packet( Flow* flow )
+{
+       Packet* pkt = new Packet;
+
+       pkt->flow = flow;
+       pkt->pkt = cooked_fin;
+       pkt->ptrs.tcph = ( tcp::TCPHdr * ) ( cooked_fin + 34 );
+       pkt->dsize = 0;
+       pkt->packet_flags &= PKT_FROM_CLIENT;
+       return pkt;
+
+}
+
+Packet *get_rst_packet( Flow* flow )
+{
+       Packet* pkt = new Packet;
+
+       pkt->flow = flow;
+       pkt->pkt = cooked_rst;
+       pkt->ptrs.tcph = ( tcp::TCPHdr * ) ( cooked_rst + 34 );
+       pkt->dsize = 0;
+       pkt->packet_flags &= PKT_FROM_CLIENT;
+       return pkt;
+
+}
+
+Packet *get_data_packet( Flow* flow )
+{
+       Packet* pkt = new Packet;
+
+       pkt->flow = flow;
+       pkt->pkt = cooked_data;
+       pkt->ptrs.tcph = ( tcp::TCPHdr * ) ( cooked_data + 34 );
+       pkt->dsize = 42;
+       pkt->packet_flags &= PKT_FROM_CLIENT;
+       return pkt;
+
+}
+#endif
+
diff --git a/src/stream/libtcp/stream_tcp_unit_test.h b/src/stream/libtcp/stream_tcp_unit_test.h
new file mode 100644 (file)
index 0000000..98d5988
--- /dev/null
@@ -0,0 +1,37 @@
+//--------------------------------------------------------------------------
+// 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.
+//--------------------------------------------------------------------------
+
+// stream_libtcp_unit_test.h author davis mcpherson <davmcphe@@cisco.com>
+// Created on: Jul 30, 2015
+
+#ifndef STREAM_LIBTCP_UNIT_TEST
+#define STREAM_LIBTCP_UNIT_TEST
+
+#include <stdint.h>
+
+#include "protocols/packet.h"
+
+Packet *get_syn_packet( Flow* flow );
+Packet *get_syn_ack_packet( Flow* flow );
+Packet *get_ack_packet( Flow* flow );
+Packet *get_fin_packet( Flow* flow );
+Packet *get_rst_packet( Flow* flow );
+Packet *get_data_packet( Flow* flow );
+
+#endif
+
index acead1077c86713eb62dd36ed5b243e15869a4d1..9e58153e209895a776fc26d4bf30bd488b3cb7a0 100644 (file)
 
 #include "tcp_segment_descriptor.h"
 
-TcpSegmentDescriptor::TcpSegmentDescriptor( Flow* flow, Packet* pkt )
+TcpSegmentDescriptor::TcpSegmentDescriptor( Flow* flow, Packet* pkt ) :
+       flow( flow )
 {
-    // TODO Auto-generated constructor stub
+    direction = flow->ssn_state.direction;
+
+    tcph = pkt->ptrs.tcph;
+    data_len = pkt->dsize;
+
+#if 1
+    src_port = ntohs(tcph->th_sport);
+    dst_port = ntohs(pkt->ptrs.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;
+    ts = 0;
+#else
+       seq = pkt->ptrs.tcph->th_seq;
+    ack = pkt->ptrs.tcph->th_ack;
+    win = pkt->ptrs.tcph->th_win;
+    end_seq = seq + (uint32_t) pkt->dsize;
+    ts = 0;
+#endif
 
 }
 
index fa8ce6ee32d362b07b0e22c48e3b4d4a56c544de..365726fcb893baf3092469c9956c8de9d436019b 100644 (file)
@@ -23,6 +23,7 @@
 #define TCP_SEGMENT_DESCRIPTOR_H
 
 #include "flow/flow.h"
+#include "protocols/tcp.h"
 #include "protocols/packet.h"
 
 class TcpSegmentDescriptor
@@ -31,6 +32,20 @@ public:
     TcpSegmentDescriptor( Flow*, Packet* );
     virtual ~TcpSegmentDescriptor();
 
+    const Flow* get_flow() const
+    {
+        return flow;
+    }
+
+    const Packet* get_pkt() const
+    {
+        return pkt;
+    }
+    const tcp::TCPHdr* get_tcph() const
+    {
+        return tcph;
+    }
+
     uint32_t get_ack() const
     {
         return ack;
@@ -41,38 +56,64 @@ public:
         return end_seq;
     }
 
-    const Flow* get_flow() const
+    uint32_t get_seq() const
     {
-        return flow;
+       return seq;
     }
 
-    const Packet* get_pkt() const
+    uint32_t get_ts() const
     {
-        return pkt;
+       return ts;
     }
 
-    uint32_t get_seq() const
+    uint16_t get_win() const
     {
-        return seq;
+       return win;
     }
 
-    uint32_t get_ts() const
+    uint16_t get_dst_port() const
+    {
+        return dst_port;
+    }
+
+    uint16_t get_src_port() const
     {
-        return ts;
+        return src_port;
     }
 
-    uint32_t get_win() const
+    uint8_t get_direction() const
     {
-        return win;
+        return direction;
+    }
+
+    void set_direction(uint8_t direction)
+    {
+        this->direction = direction;
+    }
+
+    uint32_t get_data_len() const
+    {
+        return data_len;
+    }
+
+    void set_data_len(uint32_t data_len)
+    {
+        this->data_len = data_len;
     }
 
 private:
-    Packet* pkt;
     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;
-    uint32_t win;
+    uint16_t win;
     uint32_t end_seq;
     uint32_t ts;
 };
index 29e1627058b565d61044719fad674e46f074e99e..67efdd8d7b781080d98a0e89d5742f86f85d00f6 100644 (file)
@@ -24,7 +24,16 @@ using namespace std;
 
 #include "tcp_state_handler.h"
 
-TcpStateHandler::TcpStateHandler()
+#include "main/snort_debug.h"
+
+#ifdef UNIT_TEST
+#include "test/catch.hpp"
+#include "stream_tcp_unit_test.h"
+#endif
+
+
+TcpStateHandler::TcpStateHandler() :
+               tcp_event( TcpStreamTracker::TCP_MAX_EVENTS )
 {
     // TODO Auto-generated constructor stub
 
@@ -35,63 +44,62 @@ TcpStateHandler::~TcpStateHandler()
     // TODO Auto-generated destructor stub
 
 }
+
 void TcpStateHandler::eval( TcpSegmentDescriptor &tcp_seg, TcpStreamTracker &tracker )
 {
-    TcpStateMachine::TcpEvents tcp_event = TcpStateMachine::TCP_MAX_EVENTS;
-
-    switch( tcp_event )
+    switch( tcp_event = tracker.get_tcp_event() )
     {
-    case TcpStateMachine::TCP_SYN_SENT_EVENT:
+    case TcpStreamTracker::TCP_SYN_SENT_EVENT:
         syn_sent( tcp_seg, tracker );
         break;
 
-    case TcpStateMachine::TCP_SYN_RECV_EVENT:
+    case TcpStreamTracker::TCP_SYN_RECV_EVENT:
         syn_recv( tcp_seg, tracker );
         break;
 
-    case TcpStateMachine::TCP_SYN_ACK_SENT_EVENT:
+    case TcpStreamTracker::TCP_SYN_ACK_SENT_EVENT:
         syn_ack_sent( tcp_seg, tracker );
         break;
 
-    case TcpStateMachine::TCP_SYN_ACK_RECV_EVENT:
+    case TcpStreamTracker::TCP_SYN_ACK_RECV_EVENT:
         syn_ack_recv( tcp_seg, tracker );
         break;
 
-    case TcpStateMachine::TCP_ACK_SENT_EVENT:
+    case TcpStreamTracker::TCP_ACK_SENT_EVENT:
         ack_sent( tcp_seg, tracker );
         break;
 
-    case TcpStateMachine::TCP_ACK_RECV_EVENT:
+    case TcpStreamTracker::TCP_ACK_RECV_EVENT:
         ack_recv( tcp_seg, tracker );
         break;
 
-    case TcpStateMachine::TCP_DATA_SEG_SENT_EVENT:
+    case TcpStreamTracker::TCP_DATA_SEG_SENT_EVENT:
         data_seg_sent( tcp_seg, tracker );
         break;
 
-    case TcpStateMachine::TCP_DATA_SEG_RECV_EVENT:
+    case TcpStreamTracker::TCP_DATA_SEG_RECV_EVENT:
         data_seg_recv( tcp_seg, tracker );
         break;
 
-    case TcpStateMachine::TCP_FIN_SENT_EVENT:
+    case TcpStreamTracker::TCP_FIN_SENT_EVENT:
         fin_sent( tcp_seg, tracker );
         break;
 
-    case TcpStateMachine::TCP_FIN_RECV_EVENT:
+    case TcpStreamTracker::TCP_FIN_RECV_EVENT:
         fin_recv( tcp_seg, tracker );
         break;
 
-    case TcpStateMachine::TCP_RST_SENT_EVENT:
+    case TcpStreamTracker::TCP_RST_SENT_EVENT:
         rst_sent( tcp_seg, tracker );
         break;
 
-    case TcpStateMachine::TCP_RST_RECV_EVENT:
+    case TcpStreamTracker::TCP_RST_RECV_EVENT:
         rst_recv( tcp_seg, tracker );
         break;
 
-    case TcpStateMachine::TCP_MAX_EVENTS:
+    case TcpStreamTracker::TCP_MAX_EVENTS:
     default:
-        cout << "Invalid Tcp Event " << tcp_event << endl;
+        cout << "Invalid Tcp Event " << tracker.get_tcp_event() << endl;
         break;
 
     }
@@ -99,7 +107,10 @@ void TcpStateHandler::eval( TcpSegmentDescriptor &tcp_seg, TcpStreamTracker &tra
 
 void TcpStateHandler::default_state_action( TcpSegmentDescriptor* tcp_seg, TcpStreamTracker* tracker, const char* func_name )
 {
-    cout << "Default Implementation of " << func_name << "tcp_seg: " << tcp_seg << "tracker: " << tracker << endl;
+    DebugFormat(DEBUG_STREAM_STATE, "Default Implementation of: %s tcp_seg: %p tracker: %p\n",
+            func_name, tcp_seg, tracker );
+
+    tcp_event = tracker->get_tcp_event();
 }
 
 void TcpStateHandler::syn_sent( TcpSegmentDescriptor &tcp_seg, TcpStreamTracker &tracker )
@@ -162,3 +173,192 @@ void TcpStateHandler::rst_recv(TcpSegmentDescriptor &tcp_seg, TcpStreamTracker &
     default_state_action( &tcp_seg, &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;
+
+}
+
+#endif
index afbb9b833fbb5423372e107c0519c954bb73938b..efba31eb3cbf6d88a50e053e29aabbe32ce72234 100644 (file)
@@ -35,6 +35,10 @@ public:
 
     virtual void eval(TcpSegmentDescriptor&, TcpStreamTracker&);
 
+       TcpStreamTracker::TcpEvents get_tcp_event() const {
+               return tcp_event;
+       }
+
 protected:
     virtual void syn_sent(TcpSegmentDescriptor&, TcpStreamTracker&);
     virtual void syn_recv(TcpSegmentDescriptor&, TcpStreamTracker&);
@@ -51,6 +55,7 @@ protected:
 
     void default_state_action( TcpSegmentDescriptor*, TcpStreamTracker*, const char* );
 
+    TcpStreamTracker::TcpEvents tcp_event;
 };
 
 #endif
index 349ebd12e40aeede2561025fec8f45d3ea2e7799..d31ece3a69a502192d5657fa38f3df774a18d8e7 100644 (file)
@@ -43,3 +43,8 @@ TcpStateMachine::TcpStateMachine()
 
 }
 
+void TcpStateMachine::eval( TcpSegmentDescriptor &tcp_seg, TcpStreamTracker &tracker )
+{
+    tracker.set_tcp_event( tcp_seg, tracker.is_client_tracker( ) );
+    tcp_state_handlers[ tracker.get_tcp_state( ) ]->eval( tcp_seg, tracker );
+}
index 604ab460cdd7db16b23d3ed6e82451991fc0019d..644f4c44a0a74309a9c7be267c24291f0808646b 100644 (file)
 #ifndef TCP_STATE_MACHINE_H
 #define TCP_STATE_MACHINE_H
 
+#include "tcp_state_handler.h"
+#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:
-    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
-    };
-
     virtual ~TcpStateMachine();
 
+    virtual void eval(TcpSegmentDescriptor&, TcpStreamTracker&);
+
 private:
     TcpStateMachine();
+
+    TcpStateHandler *tcp_state_handlers[ TcpStreamTracker::TCP_MAX_STATES ];
 };
 
 #endif
index cbfc62dab84e1750189662099c03a3819acd9067..57980676fd96b482b138b62bc56e1bf7a112c21a 100644 (file)
 // Created on: Jun 24, 2015
 
 #include "tcp_stream_tracker.h"
+#include "stream/stream.h"
 
-TcpStreamTracker::TcpStreamTracker( bool client )
+TcpStreamTracker::TcpStreamTracker( bool client ) :
+       client_tracker( client )
 {
-    tcp_state = ( client ) ? TcpStateMachine::TCP_CLOSED : TcpStateMachine::TCP_LISTEN;
+    tcp_state = ( client ) ? TCP_CLOSED : TCP_LISTEN;
+    tcp_event = TCP_MAX_EVENTS;
 }
 
 TcpStreamTracker::~TcpStreamTracker()
@@ -31,3 +34,51 @@ TcpStreamTracker::~TcpStreamTracker()
     // TODO Auto-generated destructor stub
 }
 
+void TcpStreamTracker::set_tcp_event( TcpSegmentDescriptor &tcp_seg, bool client )
+{
+   bool talker;
+
+    if( tcp_seg.get_direction( ) == FROM_CLIENT )
+        talker = ( client ) ? true : false;
+    else
+        talker = ( client ) ? false : true;
+
+    if( talker )
+    {
+        if( tcp_seg.get_tcph()->is_syn_only() )
+            tcp_event = TCP_SYN_SENT_EVENT;
+        else if( tcp_seg.get_tcph()->is_syn_ack() )
+            tcp_event = TCP_SYN_ACK_SENT_EVENT;
+        else if( tcp_seg.get_tcph()->is_ack() )
+        {
+            if( tcp_seg.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() )
+            tcp_event = TCP_RST_SENT_EVENT;
+        else if( tcp_seg.get_tcph()->is_fin( ) )
+            tcp_event = TCP_FIN_SENT_EVENT;
+        else
+            tcp_event = TCP_MAX_EVENTS;
+    }
+    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;
+    }
+}
index a37361bb940d6bcc94ab4c4a139f6bdad9432845..2f681eccc3ab3ddbf06dbaafb67a3744bc22c4df 100644 (file)
 #ifndef TCP_STREAM_TRACKER_H
 #define TCP_STREAM_TRACKER_H
 
-#include "tcp_state_machine.h"
+#include "stdint.h"
+
+#include "tcp_segment_descriptor.h"
 
 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 );
     virtual ~TcpStreamTracker();
 
-private:
-    TcpStateMachine::TcpStates tcp_state;
+       bool is_client_tracker() const {
+               return client_tracker;
+       }
+
+       TcpStates get_tcp_state() const {
+               return tcp_state;
+       }
+
+       void set_tcp_state(TcpStates tcp_state) {
+               this->tcp_state = tcp_state;
+       }
+
+       TcpEvents get_tcp_event() const {
+               return tcp_event;
+       }
+
+    void set_tcp_event( TcpSegmentDescriptor &tcp_seg, bool client );
+
+    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;
+       }
+
+       void set_iss(uint32_t iss) {
+               this->iss = iss;
+       }
+
+       uint32_t get_rcv_nxt() const {
+               return rcv_nxt;
+       }
+
+       void set_rcv_nxt(uint32_t rcv_nxt) {
+               this->rcv_nxt = rcv_nxt;
+       }
+
+       uint16_t get_rcv_up() const {
+               return rcv_up;
+       }
+
+       void set_rcv_up(uint16_t rcv_up) {
+               this->rcv_up = rcv_up;
+       }
+
+       uint16_t get_rcv_wnd() const {
+               return rcv_wnd;
+       }
+
+       void set_rcv_wnd(uint16_t rcv_wnd) {
+               this->rcv_wnd = rcv_wnd;
+       }
+
+       uint32_t get_snd_nxt() const {
+               return snd_nxt;
+       }
+
+       void set_snd_nxt(uint32_t snd_nxt) {
+               this->snd_nxt = snd_nxt;
+       }
+
+       uint32_t get_snd_una() const {
+               return snd_una;
+       }
+
+       void set_snd_una(uint32_t snd_una) {
+               this->snd_una = snd_una;
+       }
+
+       uint16_t get_snd_up() const {
+               return snd_up;
+       }
+
+       void set_snd_up(uint16_t snd_up) {
+               this->snd_up = snd_up;
+       }
+
+       uint32_t get_snd_wl1() const {
+               return snd_wl1;
+       }
+
+       void set_snd_wl1(uint32_t snd_wl1) {
+               this->snd_wl1 = snd_wl1;
+       }
+
+       uint32_t get_snd_wl2() const {
+               return snd_wl2;
+       }
+
+       void set_snd_wl2(uint32_t snd_wl2) {
+               this->snd_wl2 = snd_wl2;
+       }
+
+       uint16_t get_snd_wnd() const {
+               return snd_wnd;
+       }
+
+       void set_snd_wnd(uint16_t snd_wnd) {
+               this->snd_wnd = snd_wnd;
+       }
+
+       uint32_t get_ts_last_packet() const {
+               return ts_last_packet;
+       }
+
+       void set_ts_last_packet(uint32_t ts_last_packet) {
+               this->ts_last_packet = ts_last_packet;
+       }
+
+protected:
+       uint32_t snd_una; // SND.UNA - send unacknowledged
+       uint32_t snd_nxt; // SND.NXT - send next
+       uint16_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
+       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;
 
+    TcpStates tcp_state;
+    TcpEvents tcp_event;
 };
 
 #endif
index 358082d389c4d0de9e9b2bd0807d780a6c6c80c5..fd91a6aae56fe96ea4c372b8914f2361cec80e8a 100644 (file)
@@ -12,6 +12,7 @@ add_library( stream_tcp STATIC
     tcp_reassembly.cc
     tcp_session.cc
     tcp_session.h
+    tcp_closed_state.cc
     tcp_listen_state.cc
     tcp_syn_sent_state.cc
     tcp_syn_recv_state.cc
index ede40d427be5ca34b6b8cd44d4d3654c318e9c68..18f2121ade9f21e66cc2421fa004b11dbe6b07e4 100644 (file)
@@ -15,6 +15,8 @@ tcp_reassembly.h \
 tcp_reassembly.cc \
 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 \
index 9887f05b7a2e5bead4a332cc6e5bea3c7660bf7f..0eefd5d5bf7a3fe26c6426aa01d133262f66e2b8 100644 (file)
 #include "hash/sfhashfcn.h"
 #include "time/profiler.h"
 
+#ifdef UNIT_TEST
+#include "test/catch.hpp"
+#include "stream/libtcp/stream_tcp_unit_test.h"
+#endif
+
 //-------------------------------------------------------------------------
 // stream_reassemble
 //-------------------------------------------------------------------------
@@ -277,3 +282,46 @@ static const IpsApi reassemble_api =
 
 const BaseApi* ips_stream_reassemble = &reassemble_api.base;
 
+#ifdef UNIT_TEST
+
+#include "framework/cursor.h"
+
+TEST_CASE("IPS Stream Reassemble", "[ips_stream_reassemble][stream_tcp]")
+{
+    // 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( ( reassembler != nullptr ) );
+
+    Flow* flow = new Flow;
+    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 );
+        CHECK( ( reassembler->srod.enable == 0 ) );
+        CHECK( ( reassembler->srod.direction == 0 ) );
+        CHECK( ( reassembler->srod.alert == 1 ) );
+        CHECK( ( reassembler->srod.fastpath == 0 ) );
+    }
+
+    SECTION("eval enable off")
+    {
+        reassembler->srod.direction = SSN_DIR_FROM_SERVER;
+        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 );
+        CHECK( ( ss != nullptr ) );
+        CHECK( ( !ss->is_paf() ) );
+        CHECK( ( ( ( TcpSession* ) pkt->flow->session)->server.flush_policy
+                == STREAM_FLPOLICY_IGNORE ) );
+    }
+}
+
+
+#endif
index 95a3e0c5abadafc115d9767750e62d0e722fb5b7..606774406562c99b8a9dc140498f83c1868921c5 100644 (file)
@@ -118,6 +118,7 @@ int SizeOption::eval(Cursor&, Packet* pkt)
         /* the seq num wrapping case... */
         client_size = tcpssn->client.isn - tcpssn->client.l_nxt_seq;
     }
+
     if (tcpssn->server.l_nxt_seq > tcpssn->server.isn)
     {
         /* the normal case... */
diff --git a/src/stream/tcp/tcp_closed_state.cc b/src/stream/tcp/tcp_closed_state.cc
new file mode 100644 (file)
index 0000000..465dda2
--- /dev/null
@@ -0,0 +1,282 @@
+//--------------------------------------------------------------------------
+// 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 "test/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
diff --git a/src/stream/tcp/tcp_closed_state.h b/src/stream/tcp/tcp_closed_state.h
new file mode 100644 (file)
index 0000000..b545738
--- /dev/null
@@ -0,0 +1,47 @@
+//--------------------------------------------------------------------------
+// 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
index d9c3c29d21ff48ef946304021538005e4a2a4900..5a564624f5a43e6d5db7f5be292ca5577d39066c 100644 (file)
 #include "tcp_normalization.h"
 #include "tcp_reassembly.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"
 // TBD-EDM
 
 #include "main/snort_types.h"
@@ -2528,6 +2534,9 @@ void TcpSession::reset()
 
 bool TcpSession::setup(Packet*)
 {
+
+       TcpStateHandler* tsh = new TcpStateHandler;
+
     // FIXIT-L this it should not be necessary to reset here
     reset();
 
@@ -2544,6 +2553,14 @@ bool TcpSession::setup(Packet*)
     daq_flags = address_space_id = 0;
 #endif
 
+    delete tsh;
+    tsh = new TcpClosedState;
+    delete tsh;
+    tsh = new TcpListenState;
+    delete tsh;
+    tsh = new TcpSynSentState;
+    delete tsh;
+
     tcpStats.sessions++;
     return true;
 }
index a59e4b60b82e81f0ac5996107e9aac755b3f2e1e..503d42ab4291eb6e526532e9603195b208797a9b 100644 (file)
@@ -24,6 +24,10 @@ using namespace std;
 
 #include "tcp_syn_sent_state.h"
 
+#ifdef UNIT_TEST
+#include "test/catch.hpp"
+#endif
+
 TcpSynSentState::TcpSynSentState()
 {
     // TODO Auto-generated constructor stub
@@ -95,3 +99,6 @@ void TcpSynSentState::rst_recv(TcpSegmentDescriptor &tcp_seg, TcpStreamTracker &
     default_state_action( &tcp_seg, &tracker, __func__ );
 }
 
+#ifdef UNIT_TEST
+
+#endif