zeek/src/analyzer/protocol/tcp/TCP_Reassembler.h
Jon Siwek f1cef9d2a9 Fix issue w/ TCP reassembler not delivering some segments.
For example, if we have a connection between TCP "A" and TCP "B" and "A"
sends segments "1" and "2", but we don't see the first and then the next
acknowledgement from "B" is for everything up to, and including, "2",
the gap would be reported to include both segments instead of just the
first and then delivering the second.  Put generally: any segments that
weren't yet delivered because they're waiting for an earlier gap to be
filled would be dropped when an ACK comes in that includes the gap as
well as those pending segments.  (If a distinct ACK was seen for just
the gap, that situation would have worked).

Addresses BIT-1246.
2014-09-11 10:47:56 -05:00

127 lines
3.5 KiB
C++

#ifndef ANALYZER_PROTOCOL_TCP_TCP_REASSEMBLER_H
#define ANALYZER_PROTOCOL_TCP_TCP_REASSEMBLER_H
#include "Reassem.h"
#include "TCP_Endpoint.h"
class BroFile;
class Connection;
namespace analyzer { namespace tcp {
class TCP_Analyzer;
const int STOP_ON_GAP = 1;
const int PUNT_ON_PARTIAL = 1;
class TCP_Reassembler : public Reassembler {
public:
enum Type {
Direct, // deliver to destination analyzer itself
Forward, // forward to destination analyzer's children
};
TCP_Reassembler(Analyzer* arg_dst_analyzer, TCP_Analyzer* arg_tcp_analyzer,
Type arg_type, TCP_Endpoint* arg_endp);
virtual ~TCP_Reassembler();
void Done();
void SetDstAnalyzer(Analyzer* analyzer) { dst_analyzer = analyzer; }
void SetType(Type arg_type) { type = arg_type; }
TCP_Analyzer* GetTCPAnalyzer() { return tcp_analyzer; }
// Returns the volume of data buffered in the reassembler.
// First parameter returns data that is above a hole, and thus is
// waiting on the hole being filled. Second parameter returns
// data that has been processed but is awaiting an ACK to free
// it up.
//
// If we're not processing contents, then naturally each of
// these is empty.
void SizeBufferedData(uint64& waiting_on_hole, uint64& waiting_on_ack) const;
// How much data is pending delivery since it's not yet reassembled.
// Includes the data due to holes (so this value is a bit different
// from waiting_on_hole above; and is computed in a different fashion).
uint64 NumUndeliveredBytes() const
{
if ( last_block )
return last_block->upper - last_reassem_seq;
else
return 0;
}
void SetContentsFile(BroFile* f);
BroFile* GetContentsFile() const { return record_contents_file; }
void MatchUndelivered(uint64 up_to_seq, bool use_last_upper);
// Skip up to seq, as if there's a content gap.
// Can be used to skip HTTP data for performance considerations.
void SkipToSeq(uint64 seq);
int DataSent(double t, uint64 seq, int len, const u_char* data,
bool replaying=true);
void AckReceived(uint64 seq);
// Checks if we have delivered all contents that we can possibly
// deliver for this endpoint. Calls TCP_Analyzer::EndpointEOF()
// when so.
void CheckEOF();
int HasUndeliveredData() const { return HasBlocks(); }
int HadGap() const { return had_gap; }
int DataPending() const;
uint64 DataSeq() const { return LastReassemSeq(); }
void DeliverBlock(uint64 seq, int len, const u_char* data);
virtual void Deliver(uint64 seq, int len, const u_char* data);
TCP_Endpoint* Endpoint() { return endp; }
const TCP_Endpoint* Endpoint() const { return endp; }
int IsOrig() const { return endp->IsOrig(); }
bool IsSkippedContents(uint64 seq, int length) const
{ return seq + length <= seq_to_skip; }
private:
TCP_Reassembler() { }
DECLARE_SERIAL(TCP_Reassembler);
void Undelivered(uint64 up_to_seq);
void Gap(uint64 seq, uint64 len);
void RecordToSeq(uint64 start_seq, uint64 stop_seq, BroFile* f);
void RecordBlock(DataBlock* b, BroFile* f);
void RecordGap(uint64 start_seq, uint64 upper_seq, BroFile* f);
void BlockInserted(DataBlock* b);
void Overlap(const u_char* b1, const u_char* b2, uint64 n);
TCP_Endpoint* endp;
unsigned int deliver_tcp_contents:1;
unsigned int had_gap:1;
unsigned int did_EOF:1;
unsigned int skip_deliveries:1;
uint64 seq_to_skip;
bool in_delivery;
BroFile* record_contents_file; // file on which to reassemble contents
Analyzer* dst_analyzer;
TCP_Analyzer* tcp_analyzer;
Type type;
};
} } // namespace analyzer::*
#endif