]> git.ipfire.org Git - thirdparty/snort3.git/commitdiff
flow state updates
authorRuss Combs <rucombs@cisco.com>
Tue, 21 Oct 2014 04:36:56 +0000 (00:36 -0400)
committerRuss Combs <rucombs@cisco.com>
Tue, 21 Oct 2014 04:36:56 +0000 (00:36 -0400)
ChangeLog
src/flow/flow.cc
src/main.cc
src/managers/inspector_manager.cc
src/stream/icmp/icmp_session.cc
src/stream/ip/ip_defrag.cc
src/stream/ip/ip_session.cc
src/stream/tcp/tcp_session.cc
src/stream/udp/udp_session.cc

index cc4f26e6f925af002cadee3621437455e545528b..e6ab5432d6f8f90895a11e1fc95ba351276ea827 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,6 +1,7 @@
 126
 -- pulled latest from tom
 -- added paramaters to doc reference section
+-- flow state updates
 
 125
 -- discovered can't catch exceptions thrown from Lua to C++; need to
index 29915b984c845f677c192fb26856d9e562aabd3c..1da4f0e6374c0ead651ff9a5d821d75d74c519bd 100644 (file)
@@ -138,6 +138,7 @@ void Flow::restart(bool freeAppData)
 void Flow::clear(bool freeAppData)
 {
     restart(freeAppData);
+    flow_state = 0;
 
     if ( ssn_client )
     {
index bfdc1c500c13d578125bf72661f11bf5b58aa18a..f999b915f765d0c444a36626958a91c42eac1436 100644 (file)
@@ -91,7 +91,7 @@ const char* get_prompt()
 static bool use_shell(SnortConfig* sc)
 {
 #ifdef BUILD_SHELL
-    return ( snort_conf->run_flags & RUN_FLAG__SHELL );
+    return ( sc->run_flags & RUN_FLAG__SHELL );
 #else
     UNUSED(sc);
     return false;
index 65dda854fc27b25c0dcb511237247f6d4112d558..8d987ed27f04b43ad0dc432df6cd378891a3549d 100644 (file)
@@ -598,11 +598,6 @@ static inline void execute(
 void InspectorManager::bumble(Packet* p)
 {
     Flow* flow = p->flow;
-    flow->clouseau->eval(p);
-
-    if ( !flow->service )
-        return;
-
     Inspector* ins = get_binder();
 
     if ( ins )
@@ -630,16 +625,16 @@ void InspectorManager::execute (Packet* p)
     ::execute(p, fp->network.vec, fp->network.num);
     ::execute(p, fp->generic.vec, fp->generic.num);
 
+    Flow* flow = p->flow;
+
+    if ( flow && flow->clouseau && flow->service )
+        bumble(p);
+
     if ( p->dsize )
     {
-        Flow* flow = p->flow;
-
         if ( !flow )
             return;
 
-        if ( flow->clouseau && ((unsigned)p->type() & flow->clouseau->get_api()->proto_bits) )
-            bumble(p);
-
         // FIXIT-M need more than one service inspector?
         // (should be daisy chained since inspector1 will generate PDUs for
         // inspector2)
index 8cd18fb6eb63d1e74abba2edb759a55e219f60e9..f99ff5ea01ec590630b33edc0eee8692ae3c5b40 100644 (file)
@@ -194,8 +194,6 @@ static int ProcessIcmpUnreach(Packet *p)
 
 IcmpSession::IcmpSession(Flow* flow) : Session(flow)
 {
-    setup(nullptr);
-    icmpStats.created--;
 }
 
 bool IcmpSession::setup(Packet*)
index b631c7ce3c22a400df0b29d553fdc79cdacf14a5..6b84a53dc45c4cb3c9fe3f7b01194d2f089418d0 100644 (file)
@@ -208,7 +208,7 @@ static const char* const peg_names[] =
     "reassembled",
     "discards",
     "memory faults",
-    "timeouts",
+    "frag timeouts",
     "overlaps",
     "anomalies",
     "alerts",
index 0d52a1cc4ff7257dff8add6b2c2c336284400f49..982268c93a546d8ef8ea0ce7c741414d998fcc85 100644 (file)
@@ -116,7 +116,6 @@ static inline void UpdateSession (Packet* p, Flow* lws)
 
 IpSession::IpSession(Flow* flow) : Session(flow)
 {
-    memset(&tracker, 0, sizeof(tracker));
 }
 
 void IpSession::clear()
@@ -129,6 +128,7 @@ bool IpSession::setup (Packet* p)
     DEBUG_WRAP(DebugMessage(DEBUG_STREAM,
         "Stream IP session created!\n"););
 
+    memset(&tracker, 0, sizeof(tracker));
     ipStats.sessions++;
 
     sfip_copy(flow->client_ip, p->ptrs.ip_api.get_src());
index 0834402577702a3671b8787b162679e21ae5b48a..b6affde11dfa5e0be225199943c0532bc3d9099d 100644 (file)
@@ -114,9 +114,9 @@ struct TcpStats
     PegCount sessions_on_data;
     PegCount trackers_created;
     PegCount trackers_released;
-    PegCount segs_created;
+    PegCount segs_queued;
     PegCount segs_released;
-    PegCount rebuilt_segs_used;
+    PegCount segs_used;
     PegCount rebuilt_packets;
     PegCount overlaps;
     PegCount gaps;
@@ -141,9 +141,9 @@ const char* tcp_pegs[] =
     "data trackers",
     "trackers created",
     "trackers released",
-    "segs created",
+    "segs queued",
     "segs released",
-    "rebuilt segments",
+    "segs used",
     "rebuilt packets",
     "overlaps",
     "gaps",
@@ -2145,7 +2145,7 @@ static inline int _flush_to_seq (
         }
         MODULE_PROFILE_TMPSTART(s5TcpFlushPerfStats);
 
-        st->seglist_base_seq = st->seglist_next->seq + flushed_bytes;
+        st->seglist_base_seq += flushed_bytes;
 
         STREAM5_DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE,
             "setting st->seglist_base_seq to 0x%X\n", st->seglist_base_seq););
@@ -2410,13 +2410,14 @@ void TcpSession::restart_paf(Packet* p)
         listener = &tcpssn->server;
     }
 
+    // FIXTHIS-H on data / on ack must be based on flush policy
     if ( p->dsize > 0 )
         CheckFlushPolicyOnData(this, talker, listener, p);
 
-    if ( p->ptrs.tcph->th_flags & TH_ACK )
+    if ( p->ptrs.tcph->is_ack() )
         CheckFlushPolicyOnAck(this, talker, listener, p);
-
 }
+
 int Stream5FlushTalker(Packet *p, Flow *lwssn)
 {
     StreamTracker *talker = NULL;
@@ -2503,8 +2504,6 @@ static void TcpSessionClear (Flow* lwssn, TcpSession* tcpssn, int freeApplicatio
     s5_paf_clear(&tcpssn->server.paf_state);
 
     // update light-weight state
-    lwssn->flow_state = 0;
-
     if ( freeApplicationData == 2 )
         lwssn->restart(true);
     else
@@ -2667,12 +2666,7 @@ static const char* const statext[] = {
 };
 
 static const char* const flushxt[] = {
-    "NON", "FPR", "LOG", "RSP", "SLW",
-#if 0
-    "CON",
-#endif
-    "IGN", "PRO",
-    "PRE", "PAF"
+    "IGN", "FPR", "PRE", "PRO", "PAF"
 };
 
 static void TraceSegments (const StreamTracker* a)
@@ -2718,9 +2712,11 @@ static void TraceState (
             RMT(a, s_mgr.transition_seq, b)
         );
     fprintf(stdout, "\n");
+    int paf = a->splitter->is_paf() ? 2 : 0;
+
     fprintf(stdout,
-        "         FP=%s SC=%-4u FL=%-4u SL=%-5u BS=%-4u",
-        flushxt[a->flush_policy],
+        "         FP=%s:192  SC=%-4u FL=%-4u SL=%-5u BS=%-4u",
+        flushxt[a->flush_policy+paf],
         a->seg_count, a->flush_count, a->seg_bytes_logical,
         a->seglist_base_seq - b->isn
     );
@@ -2756,9 +2752,12 @@ static void TraceTCP (
     }
     TraceEvent(p, tdb, txd, rxd);
 
+    if ( !cli->s_mgr.state && !srv->s_mgr.state )
+        return;
+
     if ( lws ) TraceSession(lws);
 
-    if ( !event )
+    if ( lws && !event )
     {
         if ( cli ) TraceState(cli, srv, cdir);
         if ( srv ) TraceState(srv, cli, sdir);
@@ -4244,6 +4243,22 @@ static inline void CopyMacAddr(
 static void NewTcpSession(
     Packet* p, Flow* lwssn, StreamTcpConfig* dstPolicy, TcpSession* tmp)
 {
+    Inspector* ins = lwssn->gadget;
+
+    if ( !ins )
+        ins = lwssn->clouseau;
+
+    if ( ins )
+    {
+        stream.set_splitter(lwssn, true, ins->get_splitter(true));
+        stream.set_splitter(lwssn, false, ins->get_splitter(false));
+    }
+    else
+    {
+        stream.set_splitter(lwssn, true, new AtomSplitter(true));
+        stream.set_splitter(lwssn, false, new AtomSplitter(false));
+    }
+
     {
         STREAM5_DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE,
                     "adding TcpSession to lightweight session\n"););
@@ -4785,7 +4800,7 @@ static int ProcessTcp(
 
             /* Nothing left todo here */
         }
-        else if ( !require3Way && p->ptrs.tcph->is_syn_ack() )
+        else if ( p->ptrs.tcph->is_syn_ack() )
         {
             /* SYN-ACK from server */
             if ((lwssn->session_state == STREAM5_STATE_NONE) ||
@@ -4797,8 +4812,12 @@ static int ProcessTcp(
                 lwssn->s5_state.direction = FROM_SERVER;
             }
             lwssn->session_state |= STREAM5_STATE_SYN_ACK;
-            NewTcpSessionOnSynAck(p, lwssn, tdb, config);
-            new_ssn = 1;
+
+            if ( !require3Way || allow_midstream )
+            {
+                NewTcpSessionOnSynAck(p, lwssn, tdb, config);
+                new_ssn = 1;
+            }
             NormalTrackECN(tcpssn, (TCPHdr*)p->ptrs.tcph, require3Way);
         }
         else if (
@@ -4813,7 +4832,7 @@ static int ProcessTcp(
             NormalTrackECN(tcpssn, (TCPHdr*)p->ptrs.tcph, require3Way);
             Stream5UpdatePerfBaseState(&sfBase, lwssn, TCP_STATE_ESTABLISHED);
         }
-        else if ( allow_midstream && p->dsize )
+        else if ( p->dsize && (!require3Way || allow_midstream) )
         {
             /* create session on data, need to figure out direction, etc */
             /* Assume from client, can update later */
@@ -4821,6 +4840,7 @@ static int ProcessTcp(
                 lwssn->s5_state.direction = FROM_CLIENT;
             else
                 lwssn->s5_state.direction = FROM_SERVER;
+
             lwssn->session_state |= STREAM5_STATE_MIDSTREAM;
             lwssn->s5_state.session_flags |= SSNFLAG_MIDSTREAM;
 
@@ -4831,13 +4851,16 @@ static int ProcessTcp(
             if (lwssn->session_state & STREAM5_STATE_ESTABLISHED)
                 Stream5UpdatePerfBaseState(&sfBase, lwssn, TCP_STATE_ESTABLISHED);
         }
-        else
+        else if ( !p->dsize )
         {
+#if 0
+            // FIXIT-H delete this?
             if ( p->dsize || p->ptrs.tcph->is_syn_ack() )
             {
                 lwssn->session_state |= STREAM5_STATE_IGNORE;
                 tcpStats.sessions_ignored++;
             }
+#endif
             //else if ( !(lwssn->session_state & STREAM5_STATE_NO_PICKUP) )
             //    lwssn->session_state |= STREAM5_STATE_NO_PICKUP;
 
@@ -6080,7 +6103,7 @@ int CheckFlushPolicyOnAck(
 static void Stream5SeglistAddNode(StreamTracker *st, StreamSegment *prev,
         StreamSegment *ss)
 {
-    tcpStats.segs_created++;
+    tcpStats.segs_queued++;
 
     if(prev)
     {
@@ -6137,7 +6160,7 @@ static int Stream5SeglistDeleteNode (StreamTracker* st, StreamSegment* seg)
 
     if (seg->buffered)
     {
-        tcpStats.rebuilt_segs_used++;
+        tcpStats.segs_used++;
         st->flush_count--;
     }
 
@@ -6542,8 +6565,6 @@ char Stream5PacketsMissingTcp(Flow *lwssn, char dir)
 
 TcpSession::TcpSession(Flow* flow) : Session(flow)
 {
-    tcp_init = false;
-    reset();
 }
 
 TcpSession::~TcpSession()
@@ -6554,12 +6575,16 @@ TcpSession::~TcpSession()
 
 void TcpSession::reset()
 {
-    if ( tcp_init )
-    {
-        // FIXIT-L need to refactor around flow_state for simplicity
-        TcpSessionClear(flow, (TcpSession*)flow->session, 2);
+    if ( !tcp_init )
         return;
-    }
+
+    TcpSessionClear(flow, (TcpSession*)flow->session, 2);
+}
+
+bool TcpSession::setup (Packet*)
+{
+    lws_init = tcp_init = false;
+    ecn = 0;
 
     memset(&client, 0, sizeof(client));
     memset(&server, 0, sizeof(server));
@@ -6570,32 +6595,6 @@ void TcpSession::reset()
     daq_flags = address_space_id = 0;
 #endif
 
-    ecn = 0;
-
-    lws_init = tcp_init = false;
-}
-
-bool TcpSession::setup (Packet*)
-{
-    assert(flow->session == this);
-    reset();
-
-    Inspector* ins = flow->clouseau;
-
-    if ( !ins )
-        ins = flow->gadget;
-
-    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));
-    }
-
     tcpStats.sessions++;
     return true;
 }
@@ -6689,18 +6688,21 @@ int TcpSession::process(Packet *p)
     if ( !tcpssn->lws_init )
     {
         // FIXIT most of this now looks out of place or redundant
-        if ( p->ptrs.tcph->is_syn_only() )
+        if ( config->require_3whs() )
         {
-            /* SYN only */
-            flow->session_state = STREAM5_STATE_SYN;
-        }
-        else
-        {
-            // If we're within the "startup" window, try to handle
-            // this packet as midstream pickup -- allows for
-            // connections that already existed before snort started.
-            if ( !config->midstream_allowed(p) )
+            if ( p->ptrs.tcph->is_syn_only() )
             {
+                /* SYN only */
+                flow->session_state = STREAM5_STATE_SYN;
+            }
+            else
+            {
+                // If we're within the "startup" window, try to handle
+                // this packet as midstream pickup -- allows for
+                // connections that already existed before snort started.
+                if ( config->midstream_allowed(p) )
+                    goto midstream_pickup_allowed;
+
                  // Do nothing with this packet since we require a 3-way ;)
                 DEBUG_WRAP(
                     DebugMessage(DEBUG_STREAM_STATE, "Stream5: Requiring 3-way "
@@ -6709,6 +6711,25 @@ int TcpSession::process(Packet *p)
 
                 EventNo3whs();
                 MODULE_PROFILE_END(s5TcpPerfStats);
+#ifdef REG_TEST
+                S5TraceTCP(p, flow, &tdb, 1);
+#endif
+                return 0;
+            }
+        }
+        else
+        {
+midstream_pickup_allowed:
+            if ( 
+                !p->ptrs.tcph->is_syn_ack() &&
+                !p->dsize &&
+                !(Stream5PacketHasWscale(p) & TF_WSCALE) )
+            {
+                MODULE_PROFILE_END(s5TcpPerfStats);
+#ifdef REG_TEST
+                S5TraceTCP(p, flow, &tdb, 1);
+#endif
+                return 0;
             }
         }
         tcpssn->lws_init = true;
index fa5f0953677fa1e67a942daf2241791268cd375d..0f4bca6c6f8569e1515012b912e014880dbef1ab 100644 (file)
@@ -69,9 +69,6 @@ static void UdpSessionCleanup(Flow *lwssn)
         CloseStreamSession(&sfBase, SESSION_CLOSED_NORMALLY);
     }
 
-    lwssn->flow_state = 0;
-    lwssn->clear();
-
     udpStats.released++;
     RemoveUDPSession(&sfBase);
 }
@@ -79,13 +76,7 @@ static void UdpSessionCleanup(Flow *lwssn)
 static int ProcessUdp(
     Flow *lwssn, Packet *p, StreamUdpConfig*, SFXHASH_NODE*)
 {
-    if (lwssn->protocol != PktType::UDP)  // FIXIT-P checked by tcp, icmp, and ip too?
-    // FIXIT-L need to free lwssn and get a new one
-    {
-        DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE,
-                    "Lightweight session not UDP on UDP packet\n"););
-        return 0;
-    }
+    assert(lwssn->protocol == PktType::UDP);
 
     if ( stream.blocked_session(lwssn, p) )
         return 0;
@@ -121,6 +112,9 @@ static int ProcessUdp(
         }
     }
 
+    if ( lwssn->clouseau )
+        lwssn->clouseau->eval(p);
+
     return 0;
 }
 
@@ -130,8 +124,6 @@ static int ProcessUdp(
 
 UdpSession::UdpSession(Flow* flow) : Session(flow)
 {
-    ssn_time.tv_sec = 0;
-    ssn_time.tv_usec = 0;
 }
 
 bool UdpSession::setup(Packet* p)
@@ -150,8 +142,10 @@ bool UdpSession::setup(Packet* p)
     AddUDPSession(&sfBase);
 
     if (perfmon_config && (perfmon_config->perf_flags & SFPERF_FLOWIP))
+    {
         UpdateFlowIPState(&sfFlow, &flow->client_ip,
             &flow->server_ip, SFS_STATE_UDP_CREATED);
+    }
 
     if ( flow_con->expected_flow(flow, p) )
         return false;
@@ -163,6 +157,7 @@ bool UdpSession::setup(Packet* p)
 void UdpSession::clear()
 {
     UdpSessionCleanup(flow);
+    flow->clear();
 }
 
 void UdpSession::update_direction(
@@ -211,6 +206,8 @@ int UdpSession::process(Packet *p)
     if ( stream.expired_session(flow, p) )
     {
         UdpSessionCleanup(flow);
+        flow->restart();
+        udpStats.created++;
         udpStats.timeouts++;
     }
     ProcessUdp(flow, p, pc, hash_node);