{
tracker.set_tf_flags(TF_FORCE_FLUSH);
- if ( flush_stream(p, dir, true) )
+ // if the flow is one-way (asymmetric) then eval flush on asymmetric connection first
+ if ( !p->flow->two_way_traffic() )
+ {
+ eval_asymmetric_flush(p);
+ }
+
+ uint32_t flushed = flush_stream(p, dir, true);
+ if ( flushed )
{
if ( server_side )
tcpStats.server_cleanups++;
else
tcpStats.client_cleanups++;
+ if ( !p->flow->two_way_traffic() )
+ tcpStats.flush_on_asymmetric_flow++;
+
purge_flushed_ackd();
}
tracker.clear_tf_flags(TF_FORCE_FLUSH);
}
else
{
+ // if this is an asymmetric flow and no data has been scanned then initialize paf
+ if ( !flow->two_way_traffic() and !paf.paf_initialized() )
+ initialize_paf();
+
Packet* pdu = get_packet(flow, packet_dir, server_side);
bool pending = clear and paf.paf_initialized();
bool TcpReassemblerBase::asymmetric_flow_flushed(uint32_t flushed, snort::Packet *p)
{
- bool asymmetric = flushed && seglist.seg_count && !p->flow->two_way_traffic() && !p->ptrs.tcph->is_syn();
+ bool asymmetric = flushed && seglist.seg_count && !p->flow->two_way_traffic()
+ && ( !p->ptrs.tcph or !p->ptrs.tcph->is_syn() );
if ( asymmetric )
{
TcpStreamTracker::TcpState peer = tracker.session->get_peer_state(tracker);
else
reassembler->reset_paf();
- reassembler->eval_flush_policy_on_data(tsd.get_pkt());
+ reassembler->eval_asymmetric_flush(tsd.get_pkt());
int32_t space_left = max_queued_bytes - seglist.get_seg_bytes_total();
if ( tsd.is_data_segment() )
session->handle_data_segment(tsd);
+ Packet* p = tsd.get_pkt();
if ( flush_policy == STREAM_FLPOLICY_ON_DATA and SEQ_EQ(tsd.get_end_seq(), rcv_nxt)
- and !tsd.get_flow()->searching_for_service() )
- reassembler->finish_and_final_flush(tsd.get_flow(), true, tsd.get_pkt());
+ and !p->flow->searching_for_service() )
+ reassembler->finish_and_final_flush(p->flow, true, p);
+ else if ( !p->flow->two_way_traffic() )
+ reassembler->eval_asymmetric_flush(p);
}
uint32_t TcpStreamTracker::perform_partial_flush()