From: Russ Combs Date: Tue, 21 Oct 2014 04:36:56 +0000 (-0400) Subject: flow state updates X-Git-Tag: 3.0.0-233~1354 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=982796aeff5efbdca0a53b1956078939bdf65323;p=thirdparty%2Fsnort3.git flow state updates --- diff --git a/ChangeLog b/ChangeLog index cc4f26e6f..e6ab5432d 100644 --- 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 diff --git a/src/flow/flow.cc b/src/flow/flow.cc index 29915b984..1da4f0e63 100644 --- a/src/flow/flow.cc +++ b/src/flow/flow.cc @@ -138,6 +138,7 @@ void Flow::restart(bool freeAppData) void Flow::clear(bool freeAppData) { restart(freeAppData); + flow_state = 0; if ( ssn_client ) { diff --git a/src/main.cc b/src/main.cc index bfdc1c500..f999b915f 100644 --- a/src/main.cc +++ b/src/main.cc @@ -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; diff --git a/src/managers/inspector_manager.cc b/src/managers/inspector_manager.cc index 65dda854f..8d987ed27 100644 --- a/src/managers/inspector_manager.cc +++ b/src/managers/inspector_manager.cc @@ -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) diff --git a/src/stream/icmp/icmp_session.cc b/src/stream/icmp/icmp_session.cc index 8cd18fb6e..f99ff5ea0 100644 --- a/src/stream/icmp/icmp_session.cc +++ b/src/stream/icmp/icmp_session.cc @@ -194,8 +194,6 @@ static int ProcessIcmpUnreach(Packet *p) IcmpSession::IcmpSession(Flow* flow) : Session(flow) { - setup(nullptr); - icmpStats.created--; } bool IcmpSession::setup(Packet*) diff --git a/src/stream/ip/ip_defrag.cc b/src/stream/ip/ip_defrag.cc index b631c7ce3..6b84a53dc 100644 --- a/src/stream/ip/ip_defrag.cc +++ b/src/stream/ip/ip_defrag.cc @@ -208,7 +208,7 @@ static const char* const peg_names[] = "reassembled", "discards", "memory faults", - "timeouts", + "frag timeouts", "overlaps", "anomalies", "alerts", diff --git a/src/stream/ip/ip_session.cc b/src/stream/ip/ip_session.cc index 0d52a1cc4..982268c93 100644 --- a/src/stream/ip/ip_session.cc +++ b/src/stream/ip/ip_session.cc @@ -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()); diff --git a/src/stream/tcp/tcp_session.cc b/src/stream/tcp/tcp_session.cc index 083440257..b6affde11 100644 --- a/src/stream/tcp/tcp_session.cc +++ b/src/stream/tcp/tcp_session.cc @@ -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; diff --git a/src/stream/udp/udp_session.cc b/src/stream/udp/udp_session.cc index fa5f09536..0f4bca6c6 100644 --- a/src/stream/udp/udp_session.cc +++ b/src/stream/udp/udp_session.cc @@ -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);