Merge remote-tracking branch 'origin/topic/jsiwek/jj-bugs'

* origin/topic/jsiwek/jj-bugs:
  Fix incorrect data delivery skips after gap in HTTP Content-Range.
  Fix file analysis placement of data after gap in HTTP Content-Range.
  Fix issue w/ TCP reassembler not delivering some segments.
  Raise http_entity_data in line with data arrival.
  Implement file ID caching for MIME_Mail.
  BIT-1240: Fix MIME entity file data/gap ordering.

BIT-1240 #closed
BIT-1246 #closed
BIT-1247 #closed
BIT-1248 #closed
This commit is contained in:
Robin Sommer 2014-09-12 19:04:37 -07:00
commit 160543cbc6
30 changed files with 246 additions and 289 deletions

View file

@ -117,6 +117,45 @@ void TCP_Reassembler::SetContentsFile(BroFile* f)
record_contents_file = f;
}
static inline bool established(const TCP_Endpoint* a, const TCP_Endpoint* b)
{
return a->state == TCP_ENDPOINT_ESTABLISHED &&
b->state == TCP_ENDPOINT_ESTABLISHED;
}
static inline bool report_gap(const TCP_Endpoint* a, const TCP_Endpoint* b)
{
return content_gap &&
( BifConst::report_gaps_for_partial || established(a, b) );
}
void TCP_Reassembler::Gap(uint64 seq, uint64 len)
{
// Only report on content gaps for connections that
// are in a cleanly established state. In other
// states, these can arise falsely due to things
// like sequence number mismatches in RSTs, or
// unseen previous packets in partial connections.
// The one opportunity we lose here is on clean FIN
// handshakes, but Oh Well.
if ( report_gap(endp, endp->peer) )
{
val_list* vl = new val_list;
vl->append(dst_analyzer->BuildConnVal());
vl->append(new Val(IsOrig(), TYPE_BOOL));
vl->append(new Val(seq, TYPE_COUNT));
vl->append(new Val(len, TYPE_COUNT));
dst_analyzer->ConnectionEvent(content_gap, vl);
}
if ( type == Direct )
dst_analyzer->NextUndelivered(seq, len, IsOrig());
else
dst_analyzer->ForwardUndelivered(seq, len, IsOrig());
had_gap = true;
}
void TCP_Reassembler::Undelivered(uint64 up_to_seq)
{
@ -189,48 +228,33 @@ void TCP_Reassembler::Undelivered(uint64 up_to_seq)
if ( ! skip_deliveries )
{
// This can happen because we're processing a trace
// that's been filtered. For example, if it's just
// SYN/FIN data, then there can be data in the FIN
// packet, but it's undelievered because it's out of
// sequence.
uint64 seq = last_reassem_seq;
uint64 len = up_to_seq - last_reassem_seq;
// Only report on content gaps for connections that
// are in a cleanly established state. In other
// states, these can arise falsely due to things
// like sequence number mismatches in RSTs, or
// unseen previous packets in partial connections.
// The one opportunity we lose here is on clean FIN
// handshakes, but Oh Well.
if ( content_gap &&
(BifConst::report_gaps_for_partial ||
(endpoint->state == TCP_ENDPOINT_ESTABLISHED &&
peer->state == TCP_ENDPOINT_ESTABLISHED ) ) )
// If we have blocks that begin below up_to_seq, deliver them.
DataBlock* b = blocks;
while ( b )
{
val_list* vl = new val_list;
vl->append(dst_analyzer->BuildConnVal());
vl->append(new Val(IsOrig(), TYPE_BOOL));
vl->append(new Val(seq, TYPE_COUNT));
vl->append(new Val(len, TYPE_COUNT));
if ( b->seq < last_reassem_seq )
{
// Already delivered this block.
b = b->next;
continue;
}
dst_analyzer->ConnectionEvent(content_gap, vl);
if ( b->seq >= up_to_seq )
// Block is beyond what we need to process at this point.
break;
uint64 gap_at_seq = last_reassem_seq;
uint64 gap_len = b->seq - last_reassem_seq;
Gap(gap_at_seq, gap_len);
last_reassem_seq += gap_len;
BlockInserted(b);
b = b->next;
}
if ( type == Direct )
dst_analyzer->NextUndelivered(last_reassem_seq,
len, IsOrig());
else
{
dst_analyzer->ForwardUndelivered(last_reassem_seq,
len, IsOrig());
}
if ( up_to_seq > last_reassem_seq )
Gap(last_reassem_seq, up_to_seq - last_reassem_seq);
}
had_gap = true;
}
// We should record and match undelivered even if we are skipping