diff --git a/src/Frag.cc b/src/Frag.cc index 30bec88af1..d0389c264a 100644 --- a/src/Frag.cc +++ b/src/Frag.cc @@ -97,9 +97,9 @@ void FragReassembler::AddFragment(double t, const IP_Hdr* ip, const u_char* pkt) // Linux MTU discovery for UDP can do this, for example. s->Weird("fragment_with_DF", ip); - int offset = ip->FragOffset(); - int len = ip->TotalLen(); - int hdr_len = ip->HdrLen(); + uint16 offset = ip->FragOffset(); + uint32 len = ip->TotalLen(); + uint16 hdr_len = ip->HdrLen(); if ( len < hdr_len ) { @@ -107,7 +107,7 @@ void FragReassembler::AddFragment(double t, const IP_Hdr* ip, const u_char* pkt) return; } - int upper_seq = offset + len - hdr_len; + uint64 upper_seq = offset + len - hdr_len; if ( ! offset ) // Make sure to use the first fragment header's next field. @@ -178,7 +178,7 @@ void FragReassembler::Weird(const char* name) const } } -void FragReassembler::Overlap(const u_char* b1, const u_char* b2, int n) +void FragReassembler::Overlap(const u_char* b1, const u_char* b2, uint64 n) { if ( memcmp((const void*) b1, (const void*) b2, n) ) Weird("fragment_inconsistency"); @@ -231,7 +231,7 @@ void FragReassembler::BlockInserted(DataBlock* /* start_block */) return; // We have it all. Compute the expected size of the fragment. - int n = proto_hdr_len + frag_size; + uint64 n = proto_hdr_len + frag_size; // It's possible that we have blocks associated with this fragment // that exceed this size, if we saw MF fragments (which don't lead diff --git a/src/Frag.h b/src/Frag.h index 0d2fbed5b3..7f3a0eec02 100644 --- a/src/Frag.h +++ b/src/Frag.h @@ -34,14 +34,14 @@ public: protected: void BlockInserted(DataBlock* start_block); - void Overlap(const u_char* b1, const u_char* b2, int n); + void Overlap(const u_char* b1, const u_char* b2, uint64 n); void Weird(const char* name) const; u_char* proto_hdr; IP_Hdr* reassembled_pkt; - int proto_hdr_len; + uint16 proto_hdr_len; NetSessions* s; - int frag_size; // size of fully reassembled fragment + uint64 frag_size; // size of fully reassembled fragment uint16 next_proto; // first IPv6 fragment header's next proto field HashKey* key; diff --git a/src/Reassem.cc b/src/Reassem.cc index 19beaa0a16..27fb26561f 100644 --- a/src/Reassem.cc +++ b/src/Reassem.cc @@ -7,14 +7,9 @@ #include "Reassem.h" #include "Serializer.h" -const bool DEBUG_reassem = false; +static const bool DEBUG_reassem = false; -#ifdef DEBUG -int reassem_seen_bytes = 0; -int reassem_copied_bytes = 0; -#endif - -DataBlock::DataBlock(const u_char* data, int size, int arg_seq, +DataBlock::DataBlock(const u_char* data, uint64 size, uint64 arg_seq, DataBlock* arg_prev, DataBlock* arg_next) { seq = arg_seq; @@ -23,10 +18,6 @@ DataBlock::DataBlock(const u_char* data, int size, int arg_seq, memcpy((void*) block, (const void*) data, size); -#ifdef DEBUG - reassem_copied_bytes += size; -#endif - prev = arg_prev; next = arg_next; @@ -38,9 +29,9 @@ DataBlock::DataBlock(const u_char* data, int size, int arg_seq, Reassembler::total_size += pad_size(size) + padded_sizeof(DataBlock); } -unsigned int Reassembler::total_size = 0; +uint64 Reassembler::total_size = 0; -Reassembler::Reassembler(int init_seq, ReassemblerType arg_type) +Reassembler::Reassembler(uint64 init_seq, ReassemblerType arg_type) { blocks = last_block = 0; trim_seq = last_reassem_seq = init_seq; @@ -51,24 +42,20 @@ Reassembler::~Reassembler() ClearBlocks(); } -void Reassembler::NewBlock(double t, int seq, int len, const u_char* data) +void Reassembler::NewBlock(double t, uint64 seq, uint64 len, const u_char* data) { if ( len == 0 ) return; -#ifdef DEBUG - reassem_seen_bytes += len; -#endif + uint64 upper_seq = seq + len; - int upper_seq = seq + len; - - if ( seq_delta(upper_seq, trim_seq) <= 0 ) + if ( upper_seq <= trim_seq ) // Old data, don't do any work for it. return; - if ( seq_delta(seq, trim_seq) < 0 ) + if ( seq < trim_seq ) { // Partially old data, just keep the good stuff. - int amount_old = seq_delta(trim_seq, seq); + uint64 amount_old = trim_seq - seq; data += amount_old; seq += amount_old; @@ -86,42 +73,42 @@ void Reassembler::NewBlock(double t, int seq, int len, const u_char* data) BlockInserted(start_block); } -int Reassembler::TrimToSeq(int seq) +uint64 Reassembler::TrimToSeq(uint64 seq) { - int num_missing = 0; + uint64 num_missing = 0; // Do this accounting before looking for Undelivered data, // since that will alter last_reassem_seq. if ( blocks ) { - if ( seq_delta(blocks->seq, last_reassem_seq) > 0 ) + if ( blocks->seq > last_reassem_seq ) // An initial hole. - num_missing += seq_delta(blocks->seq, last_reassem_seq); + num_missing += blocks->seq - last_reassem_seq; } - else if ( seq_delta(seq, last_reassem_seq) > 0 ) + else if ( seq > last_reassem_seq ) { // Trimming data we never delivered. if ( ! blocks ) // We won't have any accounting based on blocks // for this hole. - num_missing += seq_delta(seq, last_reassem_seq); + num_missing += seq - last_reassem_seq; } - if ( seq_delta(seq, last_reassem_seq) > 0 ) + if ( seq > last_reassem_seq ) { // We're trimming data we never delivered. Undelivered(seq); } - while ( blocks && seq_delta(blocks->upper, seq) <= 0 ) + while ( blocks && blocks->upper <= seq ) { DataBlock* b = blocks->next; - if ( b && seq_delta(b->seq, seq) <= 0 ) + if ( b && b->seq <= seq ) { if ( blocks->upper != b->seq ) - num_missing += seq_delta(b->seq, blocks->upper); + num_missing += b->seq - blocks->upper; } else { @@ -129,7 +116,7 @@ int Reassembler::TrimToSeq(int seq) // Second half of test is for acks of FINs, which // don't get entered into the sequence space. if ( blocks->upper != seq && blocks->upper != seq - 1 ) - num_missing += seq_delta(seq, blocks->upper); + num_missing += seq - blocks->upper; } delete blocks; @@ -150,7 +137,7 @@ int Reassembler::TrimToSeq(int seq) else last_block = 0; - if ( seq_delta(seq, trim_seq) > 0 ) + if ( seq > trim_seq ) // seq is further ahead in the sequence space. trim_seq = seq; @@ -169,9 +156,9 @@ void Reassembler::ClearBlocks() last_block = 0; } -int Reassembler::TotalSize() const +uint64 Reassembler::TotalSize() const { - int size = 0; + uint64 size = 0; for ( DataBlock* b = blocks; b; b = b->next ) size += b->Size(); @@ -184,18 +171,18 @@ void Reassembler::Describe(ODesc* d) const d->Add("reassembler"); } -void Reassembler::Undelivered(int up_to_seq) +void Reassembler::Undelivered(uint64 up_to_seq) { // TrimToSeq() expects this. last_reassem_seq = up_to_seq; } -DataBlock* Reassembler::AddAndCheck(DataBlock* b, int seq, int upper, +DataBlock* Reassembler::AddAndCheck(DataBlock* b, uint64 seq, uint64 upper, const u_char* data) { if ( DEBUG_reassem ) { - DEBUG_MSG("%.6f Reassembler::AddAndCheck seq=%d, upper=%d\n", + DEBUG_MSG("%.6f Reassembler::AddAndCheck seq=%"PRIu64", upper=%"PRIu64"\n", network_time, seq, upper); } @@ -209,10 +196,10 @@ DataBlock* Reassembler::AddAndCheck(DataBlock* b, int seq, int upper, // Find the first block that doesn't come completely before the // new data. - while ( b->next && seq_delta(b->upper, seq) <= 0 ) + while ( b->next && b->upper <= seq ) b = b->next; - if ( seq_delta(b->upper, seq) <= 0 ) + if ( b->upper <= seq ) { // b is the last block, and it comes completely before // the new block. @@ -222,21 +209,20 @@ DataBlock* Reassembler::AddAndCheck(DataBlock* b, int seq, int upper, DataBlock* new_b = 0; - if ( seq_delta(upper, b->seq) <= 0 ) + if ( upper <= b->seq ) { // The new block comes completely before b. - new_b = new DataBlock(data, seq_delta(upper, seq), seq, - b->prev, b); + new_b = new DataBlock(data, upper - seq, seq, b->prev, b); if ( b == blocks ) blocks = new_b; return new_b; } // The blocks overlap, complain. - if ( seq_delta(seq, b->seq) < 0 ) + if ( seq < b->seq ) { // The new block has a prefix that comes before b. - int prefix_len = seq_delta(b->seq, seq); + uint64 prefix_len = b->seq - seq; new_b = new DataBlock(data, prefix_len, seq, b->prev, b); if ( b == blocks ) blocks = new_b; @@ -247,11 +233,11 @@ DataBlock* Reassembler::AddAndCheck(DataBlock* b, int seq, int upper, else new_b = b; - int overlap_start = seq; - int overlap_offset = seq_delta(overlap_start, b->seq); - int new_b_len = seq_delta(upper, seq); - int b_len = seq_delta(b->upper, overlap_start); - int overlap_len = min(new_b_len, b_len); + uint64 overlap_start = seq; + uint64 overlap_offset = overlap_start - b->seq; + uint64 new_b_len = upper - seq; + uint64 b_len = b->upper - overlap_start; + uint64 overlap_len = min(new_b_len, b_len); Overlap(&b->block[overlap_offset], data, overlap_len); diff --git a/src/Reassem.h b/src/Reassem.h index 1f65059e02..7b77a628d8 100644 --- a/src/Reassem.h +++ b/src/Reassem.h @@ -8,16 +8,16 @@ class DataBlock { public: - DataBlock(const u_char* data, int size, int seq, + DataBlock(const u_char* data, uint64 size, uint64 seq, DataBlock* prev, DataBlock* next); ~DataBlock(); - int Size() const { return upper - seq; } + uint64 Size() const { return upper - seq; } DataBlock* next; // next block with higher seq # DataBlock* prev; // previous block with lower seq # - int seq, upper; + uint64 seq, upper; u_char* block; }; @@ -26,22 +26,22 @@ enum ReassemblerType { REASSEM_IP, REASSEM_TCP }; class Reassembler : public BroObj { public: - Reassembler(int init_seq, ReassemblerType arg_type); + Reassembler(uint64 init_seq, ReassemblerType arg_type); virtual ~Reassembler(); - void NewBlock(double t, int seq, int len, const u_char* data); + void NewBlock(double t, uint64 seq, uint64 len, const u_char* data); // Throws away all blocks up to seq. Returns number of bytes // if not all in-sequence, 0 if they were. - int TrimToSeq(int seq); + uint64 TrimToSeq(uint64 seq); // Delete all held blocks. void ClearBlocks(); int HasBlocks() const { return blocks != 0; } - int LastReassemSeq() const { return last_reassem_seq; } + uint64 LastReassemSeq() const { return last_reassem_seq; } - int TotalSize() const; // number of bytes buffered up + uint64 TotalSize() const; // number of bytes buffered up void Describe(ODesc* d) const; @@ -49,7 +49,7 @@ public: static Reassembler* Unserialize(UnserialInfo* info); // Sum over all data buffered in some reassembler. - static unsigned int TotalMemoryAllocation() { return total_size; } + static uint64 TotalMemoryAllocation() { return total_size; } protected: Reassembler() { } @@ -58,20 +58,20 @@ protected: friend class DataBlock; - virtual void Undelivered(int up_to_seq); + virtual void Undelivered(uint64 up_to_seq); virtual void BlockInserted(DataBlock* b) = 0; - virtual void Overlap(const u_char* b1, const u_char* b2, int n) = 0; + virtual void Overlap(const u_char* b1, const u_char* b2, uint64 n) = 0; - DataBlock* AddAndCheck(DataBlock* b, int seq, - int upper, const u_char* data); + DataBlock* AddAndCheck(DataBlock* b, uint64 seq, + uint64 upper, const u_char* data); DataBlock* blocks; DataBlock* last_block; - int last_reassem_seq; - int trim_seq; // how far we've trimmed + uint64 last_reassem_seq; + uint64 trim_seq; // how far we've trimmed - static unsigned int total_size; + static uint64 total_size; }; inline DataBlock::~DataBlock() diff --git a/src/Stats.cc b/src/Stats.cc index c4b0ed45b1..6cf9a622e1 100644 --- a/src/Stats.cc +++ b/src/Stats.cc @@ -160,7 +160,7 @@ void ProfileLogger::Log() file->Write(fmt("%.06f Connections expired due to inactivity: %d\n", network_time, killed_by_inactivity)); - file->Write(fmt("%.06f Total reassembler data: %dK\n", network_time, + file->Write(fmt("%.06f Total reassembler data: %"PRIu64"K\n", network_time, Reassembler::TotalMemoryAllocation() / 1024)); // Signature engine. diff --git a/src/analyzer/Analyzer.cc b/src/analyzer/Analyzer.cc index b280cbb6f8..b840e1bbd4 100644 --- a/src/analyzer/Analyzer.cc +++ b/src/analyzer/Analyzer.cc @@ -203,7 +203,7 @@ void Analyzer::Done() finished = true; } -void Analyzer::NextPacket(int len, const u_char* data, bool is_orig, int seq, +void Analyzer::NextPacket(int len, const u_char* data, bool is_orig, uint64 seq, const IP_Hdr* ip, int caplen) { if ( skip ) @@ -250,7 +250,7 @@ void Analyzer::NextStream(int len, const u_char* data, bool is_orig) } } -void Analyzer::NextUndelivered(int seq, int len, bool is_orig) +void Analyzer::NextUndelivered(uint64 seq, int len, bool is_orig) { if ( skip ) return; @@ -287,7 +287,7 @@ void Analyzer::NextEndOfData(bool is_orig) } void Analyzer::ForwardPacket(int len, const u_char* data, bool is_orig, - int seq, const IP_Hdr* ip, int caplen) + uint64 seq, const IP_Hdr* ip, int caplen) { if ( output_handler ) output_handler->DeliverPacket(len, data, is_orig, seq, @@ -335,7 +335,7 @@ void Analyzer::ForwardStream(int len, const u_char* data, bool is_orig) AppendNewChildren(); } -void Analyzer::ForwardUndelivered(int seq, int len, bool is_orig) +void Analyzer::ForwardUndelivered(uint64 seq, int len, bool is_orig) { if ( output_handler ) output_handler->Undelivered(seq, len, is_orig); @@ -595,9 +595,9 @@ SupportAnalyzer* Analyzer::FirstSupportAnalyzer(bool orig) } void Analyzer::DeliverPacket(int len, const u_char* data, bool is_orig, - int seq, const IP_Hdr* ip, int caplen) + uint64 seq, const IP_Hdr* ip, int caplen) { - DBG_LOG(DBG_ANALYZER, "%s DeliverPacket(%d, %s, %d, %p, %d) [%s%s]", + DBG_LOG(DBG_ANALYZER, "%s DeliverPacket(%d, %s, %"PRIu64", %p, %d) [%s%s]", fmt_analyzer(this).c_str(), len, is_orig ? "T" : "F", seq, ip, caplen, fmt_bytes((const char*) data, min(40, len)), len > 40 ? "..." : ""); } @@ -609,9 +609,9 @@ void Analyzer::DeliverStream(int len, const u_char* data, bool is_orig) fmt_bytes((const char*) data, min(40, len)), len > 40 ? "..." : ""); } -void Analyzer::Undelivered(int seq, int len, bool is_orig) +void Analyzer::Undelivered(uint64 seq, int len, bool is_orig) { - DBG_LOG(DBG_ANALYZER, "%s Undelivered(%d, %d, %s)", + DBG_LOG(DBG_ANALYZER, "%s Undelivered(%"PRIu64", %d, %s)", fmt_analyzer(this).c_str(), seq, len, is_orig ? "T" : "F"); } @@ -793,7 +793,7 @@ SupportAnalyzer* SupportAnalyzer::Sibling(bool only_active) const } void SupportAnalyzer::ForwardPacket(int len, const u_char* data, bool is_orig, - int seq, const IP_Hdr* ip, int caplen) + uint64 seq, const IP_Hdr* ip, int caplen) { // We do not call parent's method, as we're replacing the functionality. @@ -834,7 +834,7 @@ void SupportAnalyzer::ForwardStream(int len, const u_char* data, bool is_orig) Parent()->DeliverStream(len, data, is_orig); } -void SupportAnalyzer::ForwardUndelivered(int seq, int len, bool is_orig) +void SupportAnalyzer::ForwardUndelivered(uint64 seq, int len, bool is_orig) { // We do not call parent's method, as we're replacing the functionality. diff --git a/src/analyzer/Analyzer.h b/src/analyzer/Analyzer.h index 578020082b..f32181b9e7 100644 --- a/src/analyzer/Analyzer.h +++ b/src/analyzer/Analyzer.h @@ -44,7 +44,7 @@ public: * Analyzer::DeliverPacket(). */ virtual void DeliverPacket(int len, const u_char* data, - bool orig, int seq, + bool orig, uint64 seq, const IP_Hdr* ip, int caplen) { } @@ -59,7 +59,7 @@ public: * Hook for receiving notification of stream gaps. Parameters are the * same as for Analyzer::Undelivered(). */ - virtual void Undelivered(int seq, int len, bool orig) { } + virtual void Undelivered(uint64 seq, int len, bool orig) { } }; /** @@ -143,7 +143,7 @@ public: * @param caplen The packet's capture length, if available. */ void NextPacket(int len, const u_char* data, bool is_orig, - int seq = -1, const IP_Hdr* ip = 0, int caplen = 0); + uint64 seq = -1, const IP_Hdr* ip = 0, int caplen = 0); /** * Passes stream input to the analyzer for processing. The analyzer @@ -173,7 +173,7 @@ public: * * @param is_orig True if this is about originator-side input. */ - void NextUndelivered(int seq, int len, bool is_orig); + void NextUndelivered(uint64 seq, int len, bool is_orig); /** * Reports a message boundary. This is a generic method that can be @@ -195,7 +195,7 @@ public: * Parameters are the same as for NextPacket(). */ virtual void ForwardPacket(int len, const u_char* data, - bool orig, int seq, + bool orig, uint64 seq, const IP_Hdr* ip, int caplen); /** @@ -212,7 +212,7 @@ public: * * Parameters are the same as for NextUndelivered(). */ - virtual void ForwardUndelivered(int seq, int len, bool orig); + virtual void ForwardUndelivered(uint64 seq, int len, bool orig); /** * Forwards an end-of-data notification on to all child analyzers. @@ -227,7 +227,7 @@ public: * Parameters are the same. */ virtual void DeliverPacket(int len, const u_char* data, bool orig, - int seq, const IP_Hdr* ip, int caplen); + uint64 seq, const IP_Hdr* ip, int caplen); /** * Hook for accessing stream input for parsing. This is called by @@ -241,7 +241,7 @@ public: * NextUndelivered() and can be overridden by derived classes. * Parameters are the same. */ - virtual void Undelivered(int seq, int len, bool orig); + virtual void Undelivered(uint64 seq, int len, bool orig); /** * Hook for accessing end-of-data notifications. This is called by @@ -749,7 +749,7 @@ public: * Parameters same as for Analyzer::ForwardPacket. */ virtual void ForwardPacket(int len, const u_char* data, bool orig, - int seq, const IP_Hdr* ip, int caplen); + uint64 seq, const IP_Hdr* ip, int caplen); /** * Passes stream input to the next sibling SupportAnalyzer if any, or @@ -769,7 +769,7 @@ public: * * Parameters same as for Analyzer::ForwardPacket. */ - virtual void ForwardUndelivered(int seq, int len, bool orig); + virtual void ForwardUndelivered(uint64 seq, int len, bool orig); protected: friend class Analyzer; diff --git a/src/analyzer/protocol/ayiya/AYIYA.cc b/src/analyzer/protocol/ayiya/AYIYA.cc index 070a3ef3e1..a1e00e9b38 100644 --- a/src/analyzer/protocol/ayiya/AYIYA.cc +++ b/src/analyzer/protocol/ayiya/AYIYA.cc @@ -22,7 +22,7 @@ void AYIYA_Analyzer::Done() Event(udp_session_done); } -void AYIYA_Analyzer::DeliverPacket(int len, const u_char* data, bool orig, int seq, const IP_Hdr* ip, int caplen) +void AYIYA_Analyzer::DeliverPacket(int len, const u_char* data, bool orig, uint64 seq, const IP_Hdr* ip, int caplen) { Analyzer::DeliverPacket(len, data, orig, seq, ip, caplen); diff --git a/src/analyzer/protocol/ayiya/AYIYA.h b/src/analyzer/protocol/ayiya/AYIYA.h index f5bb379cf4..2739ff2bba 100644 --- a/src/analyzer/protocol/ayiya/AYIYA.h +++ b/src/analyzer/protocol/ayiya/AYIYA.h @@ -12,7 +12,7 @@ public: virtual void Done(); virtual void DeliverPacket(int len, const u_char* data, bool orig, - int seq, const IP_Hdr* ip, int caplen); + uint64 seq, const IP_Hdr* ip, int caplen); static analyzer::Analyzer* InstantiateAnalyzer(Connection* conn) { return new AYIYA_Analyzer(conn); } diff --git a/src/analyzer/protocol/backdoor/BackDoor.cc b/src/analyzer/protocol/backdoor/BackDoor.cc index a466938ff6..984b2a5dcf 100644 --- a/src/analyzer/protocol/backdoor/BackDoor.cc +++ b/src/analyzer/protocol/backdoor/BackDoor.cc @@ -46,7 +46,7 @@ void BackDoorEndpoint::FinalCheckForRlogin() } } -int BackDoorEndpoint::DataSent(double /* t */, int seq, +int BackDoorEndpoint::DataSent(double /* t */, uint64 seq, int len, int caplen, const u_char* data, const IP_Hdr* /* ip */, const struct tcphdr* /* tp */) @@ -60,8 +60,8 @@ int BackDoorEndpoint::DataSent(double /* t */, int seq, if ( endp->state == tcp::TCP_ENDPOINT_PARTIAL ) is_partial = 1; - int ack = endp->AckSeq() - endp->StartSeq(); - int top_seq = seq + len; + uint64 ack = endp->ToRelativeSeqSpace(endp->AckSeq(), endp->AckWraps()); + uint64 top_seq = seq + len; if ( top_seq <= ack || top_seq <= max_top_seq ) // There is no new data in this packet. @@ -124,7 +124,7 @@ RecordVal* BackDoorEndpoint::BuildStats() return stats; } -void BackDoorEndpoint::CheckForRlogin(int seq, int len, const u_char* data) +void BackDoorEndpoint::CheckForRlogin(uint64 seq, int len, const u_char* data) { if ( rlogin_checking_done ) return; @@ -177,7 +177,7 @@ void BackDoorEndpoint::CheckForRlogin(int seq, int len, const u_char* data) if ( seq < max_top_seq ) { // trim to just the new data - int delta = max_top_seq - seq; + int64 delta = max_top_seq - seq; seq += delta; data += delta; len -= delta; @@ -255,7 +255,7 @@ void BackDoorEndpoint::RloginSignatureFound(int len) endp->TCP()->ConnectionEvent(rlogin_signature_found, vl); } -void BackDoorEndpoint::CheckForTelnet(int /* seq */, int len, const u_char* data) +void BackDoorEndpoint::CheckForTelnet(uint64 /* seq */, int len, const u_char* data) { if ( len >= 3 && data[0] == TELNET_IAC && IS_TELNET_NEGOTIATION_CMD(data[1]) ) @@ -346,7 +346,7 @@ void BackDoorEndpoint::TelnetSignatureFound(int len) endp->TCP()->ConnectionEvent(telnet_signature_found, vl); } -void BackDoorEndpoint::CheckForSSH(int seq, int len, const u_char* data) +void BackDoorEndpoint::CheckForSSH(uint64 seq, int len, const u_char* data) { if ( seq == 1 && CheckForString("SSH-", data, len) && len > 4 && (data[4] == '1' || data[4] == '2') ) @@ -363,8 +363,9 @@ void BackDoorEndpoint::CheckForSSH(int seq, int len, const u_char* data) if ( seq > max_top_seq ) { // Estimate number of packets in the sequence gap - int gap = seq - max_top_seq; - num_pkts += int((gap + DEFAULT_MTU - 1) / DEFAULT_MTU); + int64 gap = seq - max_top_seq; + if ( gap > 0 ) + num_pkts += uint64((gap + DEFAULT_MTU - 1) / DEFAULT_MTU); } ++num_pkts; @@ -388,7 +389,7 @@ void BackDoorEndpoint::CheckForSSH(int seq, int len, const u_char* data) } } -void BackDoorEndpoint::CheckForRootBackdoor(int seq, int len, const u_char* data) +void BackDoorEndpoint::CheckForRootBackdoor(uint64 seq, int len, const u_char* data) { // Check for root backdoor signature: an initial payload of // exactly "# ". @@ -397,7 +398,7 @@ void BackDoorEndpoint::CheckForRootBackdoor(int seq, int len, const u_char* data SignatureFound(root_backdoor_signature_found); } -void BackDoorEndpoint::CheckForFTP(int seq, int len, const u_char* data) +void BackDoorEndpoint::CheckForFTP(uint64 seq, int len, const u_char* data) { // Check for FTP signature // @@ -429,7 +430,7 @@ void BackDoorEndpoint::CheckForFTP(int seq, int len, const u_char* data) SignatureFound(ftp_signature_found); } -void BackDoorEndpoint::CheckForNapster(int seq, int len, const u_char* data) +void BackDoorEndpoint::CheckForNapster(uint64 seq, int len, const u_char* data) { // Check for Napster signature "GETfoobar" or "SENDfoobar" where // "foobar" is the Napster handle associated with the request @@ -449,7 +450,7 @@ void BackDoorEndpoint::CheckForNapster(int seq, int len, const u_char* data) SignatureFound(napster_signature_found); } -void BackDoorEndpoint::CheckForSMTP(int seq, int len, const u_char* data) +void BackDoorEndpoint::CheckForSMTP(uint64 seq, int len, const u_char* data) { const char* smtp_handshake[] = { "HELO", "EHLO", 0 }; @@ -460,7 +461,7 @@ void BackDoorEndpoint::CheckForSMTP(int seq, int len, const u_char* data) SignatureFound(smtp_signature_found); } -void BackDoorEndpoint::CheckForIRC(int seq, int len, const u_char* data) +void BackDoorEndpoint::CheckForIRC(uint64 seq, int len, const u_char* data) { if ( seq != 1 || is_partial ) return; @@ -475,7 +476,7 @@ void BackDoorEndpoint::CheckForIRC(int seq, int len, const u_char* data) SignatureFound(irc_signature_found); } -void BackDoorEndpoint::CheckForGnutella(int seq, int len, const u_char* data) +void BackDoorEndpoint::CheckForGnutella(uint64 seq, int len, const u_char* data) { // After connecting to the server, the connecting client says: // @@ -492,13 +493,13 @@ void BackDoorEndpoint::CheckForGnutella(int seq, int len, const u_char* data) SignatureFound(gnutella_signature_found); } -void BackDoorEndpoint::CheckForGaoBot(int seq, int len, const u_char* data) +void BackDoorEndpoint::CheckForGaoBot(uint64 seq, int len, const u_char* data) { if ( seq == 1 && CheckForString("220 Bot Server (Win32)", data, len) ) SignatureFound(gaobot_signature_found); } -void BackDoorEndpoint::CheckForKazaa(int seq, int len, const u_char* data) +void BackDoorEndpoint::CheckForKazaa(uint64 seq, int len, const u_char* data) { // *Some*, though not all, KaZaa connections begin with: // @@ -565,7 +566,7 @@ int is_absolute_url(const u_char* data, int len) return *abs_url_sig_pos == '\0'; } -void BackDoorEndpoint::CheckForHTTP(int seq, int len, const u_char* data) +void BackDoorEndpoint::CheckForHTTP(uint64 seq, int len, const u_char* data) { // According to the RFC, we should look for // ' SP SP HTTP/ CR LF' @@ -629,7 +630,7 @@ void BackDoorEndpoint::CheckForHTTP(int seq, int len, const u_char* data) } } -void BackDoorEndpoint::CheckForHTTPProxy(int /* seq */, int len, +void BackDoorEndpoint::CheckForHTTPProxy(uint64 /* seq */, int len, const u_char* data) { // Proxy ONLY accepts absolute URI's: "The absoluteURI form is @@ -713,7 +714,7 @@ void BackDoor_Analyzer::Init() } void BackDoor_Analyzer::DeliverPacket(int len, const u_char* data, bool is_orig, - int seq, const IP_Hdr* ip, int caplen) + uint64 seq, const IP_Hdr* ip, int caplen) { Analyzer::DeliverPacket(len, data, is_orig, seq, ip, caplen); diff --git a/src/analyzer/protocol/backdoor/BackDoor.h b/src/analyzer/protocol/backdoor/BackDoor.h index 5bc8a67381..b1b95ca3f8 100644 --- a/src/analyzer/protocol/backdoor/BackDoor.h +++ b/src/analyzer/protocol/backdoor/BackDoor.h @@ -14,7 +14,7 @@ class BackDoorEndpoint { public: BackDoorEndpoint(tcp::TCP_Endpoint* e); - int DataSent(double t, int seq, int len, int caplen, const u_char* data, + int DataSent(double t, uint64 seq, int len, int caplen, const u_char* data, const IP_Hdr* ip, const struct tcphdr* tp); RecordVal* BuildStats(); @@ -22,23 +22,23 @@ public: void FinalCheckForRlogin(); protected: - void CheckForRlogin(int seq, int len, const u_char* data); + void CheckForRlogin(uint64 seq, int len, const u_char* data); void RloginSignatureFound(int len); - void CheckForTelnet(int seq, int len, const u_char* data); + void CheckForTelnet(uint64 seq, int len, const u_char* data); void TelnetSignatureFound(int len); - void CheckForSSH(int seq, int len, const u_char* data); - void CheckForFTP(int seq, int len, const u_char* data); - void CheckForRootBackdoor(int seq, int len, const u_char* data); - void CheckForNapster(int seq, int len, const u_char* data); - void CheckForGnutella(int seq, int len, const u_char* data); - void CheckForKazaa(int seq, int len, const u_char* data); - void CheckForHTTP(int seq, int len, const u_char* data); - void CheckForHTTPProxy(int seq, int len, const u_char* data); - void CheckForSMTP(int seq, int len, const u_char* data); - void CheckForIRC(int seq, int len, const u_char* data); - void CheckForGaoBot(int seq, int len, const u_char* data); + void CheckForSSH(uint64 seq, int len, const u_char* data); + void CheckForFTP(uint64 seq, int len, const u_char* data); + void CheckForRootBackdoor(uint64 seq, int len, const u_char* data); + void CheckForNapster(uint64 seq, int len, const u_char* data); + void CheckForGnutella(uint64 seq, int len, const u_char* data); + void CheckForKazaa(uint64 seq, int len, const u_char* data); + void CheckForHTTP(uint64 seq, int len, const u_char* data); + void CheckForHTTPProxy(uint64 seq, int len, const u_char* data); + void CheckForSMTP(uint64 seq, int len, const u_char* data); + void CheckForIRC(uint64 seq, int len, const u_char* data); + void CheckForGaoBot(uint64 seq, int len, const u_char* data); void SignatureFound(EventHandlerPtr e, int do_orig = 0); @@ -48,11 +48,11 @@ protected: tcp::TCP_Endpoint* endp; int is_partial; - int max_top_seq; + uint64 max_top_seq; int rlogin_checking_done; int rlogin_num_null; - int rlogin_string_separator_pos; + uint64 rlogin_string_separator_pos; int rlogin_slash_seen; uint32 num_pkts; @@ -80,7 +80,7 @@ protected: // We support both packet and stream input, and can be instantiated // even if the TCP analyzer is not yet reassembling. virtual void DeliverPacket(int len, const u_char* data, bool is_orig, - int seq, const IP_Hdr* ip, int caplen); + uint64 seq, const IP_Hdr* ip, int caplen); virtual void DeliverStream(int len, const u_char* data, bool is_orig); void StatEvent(); diff --git a/src/analyzer/protocol/bittorrent/BitTorrent.cc b/src/analyzer/protocol/bittorrent/BitTorrent.cc index 99fd9dc132..cb6fc0945e 100644 --- a/src/analyzer/protocol/bittorrent/BitTorrent.cc +++ b/src/analyzer/protocol/bittorrent/BitTorrent.cc @@ -68,7 +68,7 @@ void BitTorrent_Analyzer::DeliverStream(int len, const u_char* data, bool orig) } } -void BitTorrent_Analyzer::Undelivered(int seq, int len, bool orig) +void BitTorrent_Analyzer::Undelivered(uint64 seq, int len, bool orig) { tcp::TCP_ApplicationAnalyzer::Undelivered(seq, len, orig); diff --git a/src/analyzer/protocol/bittorrent/BitTorrent.h b/src/analyzer/protocol/bittorrent/BitTorrent.h index 7739463052..2e303f4038 100644 --- a/src/analyzer/protocol/bittorrent/BitTorrent.h +++ b/src/analyzer/protocol/bittorrent/BitTorrent.h @@ -16,7 +16,7 @@ public: virtual void Done(); virtual void DeliverStream(int len, const u_char* data, bool orig); - virtual void Undelivered(int seq, int len, bool orig); + virtual void Undelivered(uint64 seq, int len, bool orig); virtual void EndpointEOF(bool is_orig); static analyzer::Analyzer* InstantiateAnalyzer(Connection* conn) diff --git a/src/analyzer/protocol/bittorrent/BitTorrentTracker.cc b/src/analyzer/protocol/bittorrent/BitTorrentTracker.cc index 98adcaa610..43ee6a2b21 100644 --- a/src/analyzer/protocol/bittorrent/BitTorrentTracker.cc +++ b/src/analyzer/protocol/bittorrent/BitTorrentTracker.cc @@ -207,7 +207,7 @@ void BitTorrentTracker_Analyzer::ServerReply(int len, const u_char* data) } } -void BitTorrentTracker_Analyzer::Undelivered(int seq, int len, bool orig) +void BitTorrentTracker_Analyzer::Undelivered(uint64 seq, int len, bool orig) { tcp::TCP_ApplicationAnalyzer::Undelivered(seq, len, orig); diff --git a/src/analyzer/protocol/bittorrent/BitTorrentTracker.h b/src/analyzer/protocol/bittorrent/BitTorrentTracker.h index b041e556b7..2fa5d684cd 100644 --- a/src/analyzer/protocol/bittorrent/BitTorrentTracker.h +++ b/src/analyzer/protocol/bittorrent/BitTorrentTracker.h @@ -49,7 +49,7 @@ public: virtual void Done(); virtual void DeliverStream(int len, const u_char* data, bool orig); - virtual void Undelivered(int seq, int len, bool orig); + virtual void Undelivered(uint64 seq, int len, bool orig); virtual void EndpointEOF(bool is_orig); static analyzer::Analyzer* InstantiateAnalyzer(Connection* conn) diff --git a/src/analyzer/protocol/conn-size/ConnSize.cc b/src/analyzer/protocol/conn-size/ConnSize.cc index 227a4b1be2..5bfeb2bf90 100644 --- a/src/analyzer/protocol/conn-size/ConnSize.cc +++ b/src/analyzer/protocol/conn-size/ConnSize.cc @@ -36,7 +36,7 @@ void ConnSize_Analyzer::Done() Analyzer::Done(); } -void ConnSize_Analyzer::DeliverPacket(int len, const u_char* data, bool is_orig, int seq, const IP_Hdr* ip, int caplen) +void ConnSize_Analyzer::DeliverPacket(int len, const u_char* data, bool is_orig, uint64 seq, const IP_Hdr* ip, int caplen) { Analyzer::DeliverPacket(len, data, is_orig, seq, ip, caplen); diff --git a/src/analyzer/protocol/conn-size/ConnSize.h b/src/analyzer/protocol/conn-size/ConnSize.h index 25f096dd32..ec3b85c0d9 100644 --- a/src/analyzer/protocol/conn-size/ConnSize.h +++ b/src/analyzer/protocol/conn-size/ConnSize.h @@ -26,7 +26,7 @@ public: protected: virtual void DeliverPacket(int len, const u_char* data, bool is_orig, - int seq, const IP_Hdr* ip, int caplen); + uint64 seq, const IP_Hdr* ip, int caplen); uint64_t orig_bytes; diff --git a/src/analyzer/protocol/dhcp/DHCP.cc b/src/analyzer/protocol/dhcp/DHCP.cc index 1fa8759fbf..78b1c6be69 100644 --- a/src/analyzer/protocol/dhcp/DHCP.cc +++ b/src/analyzer/protocol/dhcp/DHCP.cc @@ -21,7 +21,7 @@ void DHCP_Analyzer::Done() } void DHCP_Analyzer::DeliverPacket(int len, const u_char* data, - bool orig, int seq, const IP_Hdr* ip, int caplen) + bool orig, uint64 seq, const IP_Hdr* ip, int caplen) { Analyzer::DeliverPacket(len, data, orig, seq, ip, caplen); interp->NewData(orig, data, data + len); diff --git a/src/analyzer/protocol/dhcp/DHCP.h b/src/analyzer/protocol/dhcp/DHCP.h index a1c06e8b85..7633d71351 100644 --- a/src/analyzer/protocol/dhcp/DHCP.h +++ b/src/analyzer/protocol/dhcp/DHCP.h @@ -14,7 +14,7 @@ public: virtual void Done(); virtual void DeliverPacket(int len, const u_char* data, bool orig, - int seq, const IP_Hdr* ip, int caplen); + uint64 seq, const IP_Hdr* ip, int caplen); static analyzer::Analyzer* InstantiateAnalyzer(Connection* conn) { return new DHCP_Analyzer(conn); } diff --git a/src/analyzer/protocol/dnp3/DNP3.cc b/src/analyzer/protocol/dnp3/DNP3.cc index ee90a0c74d..9d9ddf0c35 100644 --- a/src/analyzer/protocol/dnp3/DNP3.cc +++ b/src/analyzer/protocol/dnp3/DNP3.cc @@ -153,7 +153,7 @@ void DNP3_Analyzer::DeliverStream(int len, const u_char* data, bool orig) } } -void DNP3_Analyzer::Undelivered(int seq, int len, bool orig) +void DNP3_Analyzer::Undelivered(uint64 seq, int len, bool orig) { TCP_ApplicationAnalyzer::Undelivered(seq, len, orig); interp->NewGap(orig, len); diff --git a/src/analyzer/protocol/dnp3/DNP3.h b/src/analyzer/protocol/dnp3/DNP3.h index b84d3874b4..a0578808a8 100644 --- a/src/analyzer/protocol/dnp3/DNP3.h +++ b/src/analyzer/protocol/dnp3/DNP3.h @@ -14,7 +14,7 @@ public: virtual void Done(); virtual void DeliverStream(int len, const u_char* data, bool orig); - virtual void Undelivered(int seq, int len, bool orig); + virtual void Undelivered(uint64 seq, int len, bool orig); virtual void EndpointEOF(bool is_orig); static Analyzer* InstantiateAnalyzer(Connection* conn) diff --git a/src/analyzer/protocol/dns/DNS.cc b/src/analyzer/protocol/dns/DNS.cc index 649237c75a..1c77fc6b51 100644 --- a/src/analyzer/protocol/dns/DNS.cc +++ b/src/analyzer/protocol/dns/DNS.cc @@ -1173,7 +1173,7 @@ void DNS_Analyzer::Done() } void DNS_Analyzer::DeliverPacket(int len, const u_char* data, bool orig, - int seq, const IP_Hdr* ip, int caplen) + uint64 seq, const IP_Hdr* ip, int caplen) { tcp::TCP_ApplicationAnalyzer::DeliverPacket(len, data, orig, seq, ip, caplen); diff --git a/src/analyzer/protocol/dns/DNS.h b/src/analyzer/protocol/dns/DNS.h index af4b8de22f..2cc1615b04 100644 --- a/src/analyzer/protocol/dns/DNS.h +++ b/src/analyzer/protocol/dns/DNS.h @@ -258,7 +258,7 @@ public: ~DNS_Analyzer(); virtual void DeliverPacket(int len, const u_char* data, bool orig, - int seq, const IP_Hdr* ip, int caplen); + uint64 seq, const IP_Hdr* ip, int caplen); virtual void Init(); virtual void Done(); diff --git a/src/analyzer/protocol/file/File.cc b/src/analyzer/protocol/file/File.cc index 4ea8dffaa8..b7e00c7fa4 100644 --- a/src/analyzer/protocol/file/File.cc +++ b/src/analyzer/protocol/file/File.cc @@ -40,7 +40,7 @@ void File_Analyzer::DeliverStream(int len, const u_char* data, bool orig) orig, file_id_resp); } -void File_Analyzer::Undelivered(int seq, int len, bool orig) +void File_Analyzer::Undelivered(uint64 seq, int len, bool orig) { TCP_ApplicationAnalyzer::Undelivered(seq, len, orig); diff --git a/src/analyzer/protocol/file/File.h b/src/analyzer/protocol/file/File.h index 9376dcc7c3..0f33b5a395 100644 --- a/src/analyzer/protocol/file/File.h +++ b/src/analyzer/protocol/file/File.h @@ -17,7 +17,7 @@ public: virtual void DeliverStream(int len, const u_char* data, bool orig); - void Undelivered(int seq, int len, bool orig); + void Undelivered(uint64 seq, int len, bool orig); // static analyzer::Analyzer* InstantiateAnalyzer(Connection* conn) // { return new File_Analyzer(conn); } diff --git a/src/analyzer/protocol/gtpv1/GTPv1.cc b/src/analyzer/protocol/gtpv1/GTPv1.cc index 0a94a28554..361e602b5f 100644 --- a/src/analyzer/protocol/gtpv1/GTPv1.cc +++ b/src/analyzer/protocol/gtpv1/GTPv1.cc @@ -23,7 +23,7 @@ void GTPv1_Analyzer::Done() Event(udp_session_done); } -void GTPv1_Analyzer::DeliverPacket(int len, const u_char* data, bool orig, int seq, const IP_Hdr* ip, int caplen) +void GTPv1_Analyzer::DeliverPacket(int len, const u_char* data, bool orig, uint64 seq, const IP_Hdr* ip, int caplen) { Analyzer::DeliverPacket(len, data, orig, seq, ip, caplen); try diff --git a/src/analyzer/protocol/gtpv1/GTPv1.h b/src/analyzer/protocol/gtpv1/GTPv1.h index b58405ea7f..eebaf1d83e 100644 --- a/src/analyzer/protocol/gtpv1/GTPv1.h +++ b/src/analyzer/protocol/gtpv1/GTPv1.h @@ -12,7 +12,7 @@ public: virtual void Done(); virtual void DeliverPacket(int len, const u_char* data, bool orig, - int seq, const IP_Hdr* ip, int caplen); + uint64 seq, const IP_Hdr* ip, int caplen); static analyzer::Analyzer* InstantiateAnalyzer(Connection* conn) { return new GTPv1_Analyzer(conn); } diff --git a/src/analyzer/protocol/http/HTTP.cc b/src/analyzer/protocol/http/HTTP.cc index feddeb00a9..02b6947b9f 100644 --- a/src/analyzer/protocol/http/HTTP.cc +++ b/src/analyzer/protocol/http/HTTP.cc @@ -1129,11 +1129,11 @@ void HTTP_Analyzer::DeliverStream(int len, const u_char* data, bool is_orig) } } -void HTTP_Analyzer::Undelivered(int seq, int len, bool is_orig) +void HTTP_Analyzer::Undelivered(uint64 seq, int len, bool is_orig) { tcp::TCP_ApplicationAnalyzer::Undelivered(seq, len, is_orig); - // DEBUG_MSG("Undelivered from %d: %d bytes\n", seq, length); + // DEBUG_MSG("Undelivered from %"PRIu64": %d bytes\n", seq, length); HTTP_Message* msg = is_orig ? request_message : reply_message; @@ -1145,7 +1145,7 @@ void HTTP_Analyzer::Undelivered(int seq, int len, bool is_orig) { if ( msg ) msg->SubmitEvent(mime::MIME_EVENT_CONTENT_GAP, - fmt("seq=%d, len=%d", seq, len)); + fmt("seq=%"PRIu64", len=%d", seq, len)); } // Check if the content gap falls completely within a message body diff --git a/src/analyzer/protocol/http/HTTP.h b/src/analyzer/protocol/http/HTTP.h index 0318dc9601..826903d795 100644 --- a/src/analyzer/protocol/http/HTTP.h +++ b/src/analyzer/protocol/http/HTTP.h @@ -162,7 +162,7 @@ public: HTTP_Analyzer(Connection* conn); ~HTTP_Analyzer(); - void Undelivered(tcp::TCP_Endpoint* sender, int seq, int len); + void Undelivered(tcp::TCP_Endpoint* sender, uint64 seq, int len); void HTTP_Header(int is_orig, mime::MIME_Header* h); void HTTP_EntityData(int is_orig, const BroString* entity_data); @@ -178,7 +178,7 @@ public: // Overriden from Analyzer. virtual void Done(); virtual void DeliverStream(int len, const u_char* data, bool orig); - virtual void Undelivered(int seq, int len, bool orig); + virtual void Undelivered(uint64 seq, int len, bool orig); // Overriden from tcp::TCP_ApplicationAnalyzer virtual void EndpointEOF(bool is_orig); diff --git a/src/analyzer/protocol/icmp/ICMP.cc b/src/analyzer/protocol/icmp/ICMP.cc index 510d3b3a80..393b5536e8 100644 --- a/src/analyzer/protocol/icmp/ICMP.cc +++ b/src/analyzer/protocol/icmp/ICMP.cc @@ -31,7 +31,7 @@ void ICMP_Analyzer::Done() } void ICMP_Analyzer::DeliverPacket(int len, const u_char* data, - bool is_orig, int seq, const IP_Hdr* ip, int caplen) + bool is_orig, uint64 seq, const IP_Hdr* ip, int caplen) { assert(ip); diff --git a/src/analyzer/protocol/icmp/ICMP.h b/src/analyzer/protocol/icmp/ICMP.h index e371f53889..116348cce6 100644 --- a/src/analyzer/protocol/icmp/ICMP.h +++ b/src/analyzer/protocol/icmp/ICMP.h @@ -29,7 +29,7 @@ protected: virtual void Done(); virtual void DeliverPacket(int len, const u_char* data, bool orig, - int seq, const IP_Hdr* ip, int caplen); + uint64 seq, const IP_Hdr* ip, int caplen); virtual bool IsReuse(double t, const u_char* pkt); virtual unsigned int MemoryAllocation() const; diff --git a/src/analyzer/protocol/interconn/InterConn.cc b/src/analyzer/protocol/interconn/InterConn.cc index 4b298eaa52..eb529cbb6d 100644 --- a/src/analyzer/protocol/interconn/InterConn.cc +++ b/src/analyzer/protocol/interconn/InterConn.cc @@ -24,7 +24,7 @@ InterConnEndpoint::InterConnEndpoint(tcp::TCP_Endpoint* e) #define NORMAL_LINE_LENGTH 80 -int InterConnEndpoint::DataSent(double t, int seq, int len, int caplen, +int InterConnEndpoint::DataSent(double t, uint64 seq, int len, int caplen, const u_char* data, const IP_Hdr* /* ip */, const struct tcphdr* /* tp */) { @@ -37,8 +37,8 @@ int InterConnEndpoint::DataSent(double t, int seq, int len, int caplen, if ( endp->state == tcp::TCP_ENDPOINT_PARTIAL ) is_partial = 1; - int ack = endp->AckSeq() - endp->StartSeq(); - int top_seq = seq + len; + uint64 ack = endp->ToRelativeSeqSpace(endp->AckSeq(), endp->AckWraps()); + uint64 top_seq = seq + len; if ( top_seq <= ack || top_seq <= max_top_seq ) // There is no new data in this packet @@ -46,7 +46,7 @@ int InterConnEndpoint::DataSent(double t, int seq, int len, int caplen, if ( seq < max_top_seq ) { // Only consider new data - int amount_seen = max_top_seq - seq; + int64 amount_seen = max_top_seq - seq; seq += amount_seen; data += amount_seen; len -= amount_seen; @@ -184,7 +184,7 @@ void InterConn_Analyzer::Init() } void InterConn_Analyzer::DeliverPacket(int len, const u_char* data, - bool is_orig, int seq, const IP_Hdr* ip, int caplen) + bool is_orig, uint64 seq, const IP_Hdr* ip, int caplen) { tcp::TCP_ApplicationAnalyzer::DeliverPacket(len, data, is_orig, seq, ip, caplen); diff --git a/src/analyzer/protocol/interconn/InterConn.h b/src/analyzer/protocol/interconn/InterConn.h index b13abecab1..a485e05082 100644 --- a/src/analyzer/protocol/interconn/InterConn.h +++ b/src/analyzer/protocol/interconn/InterConn.h @@ -13,7 +13,7 @@ class InterConnEndpoint : public BroObj { public: InterConnEndpoint(tcp::TCP_Endpoint* e); - int DataSent(double t, int seq, int len, int caplen, const u_char* data, + int DataSent(double t, uint64 seq, int len, int caplen, const u_char* data, const IP_Hdr* ip, const struct tcphdr* tp); RecordVal* BuildStats(); @@ -25,7 +25,7 @@ protected: tcp::TCP_Endpoint* endp; double last_keystroke_time; - int max_top_seq; + uint64 max_top_seq; uint32 num_pkts; uint32 num_keystrokes_two_in_a_row; uint32 num_normal_interarrivals; @@ -56,7 +56,7 @@ protected: // We support both packet and stream input and can be put in place even // if the TCP analyzer is not yet reassembling. virtual void DeliverPacket(int len, const u_char* data, bool is_orig, - int seq, const IP_Hdr* ip, int caplen); + uint64 seq, const IP_Hdr* ip, int caplen); virtual void DeliverStream(int len, const u_char* data, bool is_orig); void StatEvent(); diff --git a/src/analyzer/protocol/modbus/Modbus.cc b/src/analyzer/protocol/modbus/Modbus.cc index 9d216d356b..f003ad6cc5 100644 --- a/src/analyzer/protocol/modbus/Modbus.cc +++ b/src/analyzer/protocol/modbus/Modbus.cc @@ -31,7 +31,7 @@ void ModbusTCP_Analyzer::DeliverStream(int len, const u_char* data, bool orig) interp->NewData(orig, data, data + len); } -void ModbusTCP_Analyzer::Undelivered(int seq, int len, bool orig) +void ModbusTCP_Analyzer::Undelivered(uint64 seq, int len, bool orig) { TCP_ApplicationAnalyzer::Undelivered(seq, len, orig); interp->NewGap(orig, len); diff --git a/src/analyzer/protocol/modbus/Modbus.h b/src/analyzer/protocol/modbus/Modbus.h index 6f566be828..41448f69e3 100644 --- a/src/analyzer/protocol/modbus/Modbus.h +++ b/src/analyzer/protocol/modbus/Modbus.h @@ -14,7 +14,7 @@ public: virtual void Done(); virtual void DeliverStream(int len, const u_char* data, bool orig); - virtual void Undelivered(int seq, int len, bool orig); + virtual void Undelivered(uint64 seq, int len, bool orig); virtual void EndpointEOF(bool is_orig); static analyzer::Analyzer* InstantiateAnalyzer(Connection* conn) diff --git a/src/analyzer/protocol/ncp/NCP.cc b/src/analyzer/protocol/ncp/NCP.cc index 75b6c9f4be..3858f0b2ad 100644 --- a/src/analyzer/protocol/ncp/NCP.cc +++ b/src/analyzer/protocol/ncp/NCP.cc @@ -211,7 +211,7 @@ void Contents_NCP_Analyzer::DeliverStream(int len, const u_char* data, bool orig } } -void Contents_NCP_Analyzer::Undelivered(int seq, int len, bool orig) +void Contents_NCP_Analyzer::Undelivered(uint64 seq, int len, bool orig) { tcp::TCP_SupportAnalyzer::Undelivered(seq, len, orig); diff --git a/src/analyzer/protocol/ncp/NCP.h b/src/analyzer/protocol/ncp/NCP.h index 34174df74e..2e06babb8c 100644 --- a/src/analyzer/protocol/ncp/NCP.h +++ b/src/analyzer/protocol/ncp/NCP.h @@ -90,7 +90,7 @@ public: protected: virtual void DeliverStream(int len, const u_char* data, bool orig); - virtual void Undelivered(int seq, int len, bool orig); + virtual void Undelivered(uint64 seq, int len, bool orig); NCP_FrameBuffer buffer; NCP_Session* session; diff --git a/src/analyzer/protocol/netbios/NetbiosSSN.cc b/src/analyzer/protocol/netbios/NetbiosSSN.cc index 4d6ed8e1f1..d65a152b2f 100644 --- a/src/analyzer/protocol/netbios/NetbiosSSN.cc +++ b/src/analyzer/protocol/netbios/NetbiosSSN.cc @@ -513,7 +513,7 @@ void NetbiosSSN_Analyzer::ConnectionClosed(tcp::TCP_Endpoint* endpoint, } void NetbiosSSN_Analyzer::DeliverPacket(int len, const u_char* data, bool orig, - int seq, const IP_Hdr* ip, int caplen) + uint64 seq, const IP_Hdr* ip, int caplen) { tcp::TCP_ApplicationAnalyzer::DeliverPacket(len, data, orig, seq, ip, caplen); diff --git a/src/analyzer/protocol/netbios/NetbiosSSN.h b/src/analyzer/protocol/netbios/NetbiosSSN.h index 7c2728ef9a..7fbe967841 100644 --- a/src/analyzer/protocol/netbios/NetbiosSSN.h +++ b/src/analyzer/protocol/netbios/NetbiosSSN.h @@ -146,7 +146,7 @@ public: virtual void Done(); virtual void DeliverPacket(int len, const u_char* data, bool orig, - int seq, const IP_Hdr* ip, int caplen); + uint64 seq, const IP_Hdr* ip, int caplen); static analyzer::Analyzer* InstantiateAnalyzer(Connection* conn) { return new NetbiosSSN_Analyzer(conn); } diff --git a/src/analyzer/protocol/ntp/NTP.cc b/src/analyzer/protocol/ntp/NTP.cc index b4b63d5634..5778da9a0e 100644 --- a/src/analyzer/protocol/ntp/NTP.cc +++ b/src/analyzer/protocol/ntp/NTP.cc @@ -25,7 +25,7 @@ void NTP_Analyzer::Done() Event(udp_session_done); } -void NTP_Analyzer::DeliverPacket(int len, const u_char* data, bool is_orig, int seq, const IP_Hdr* ip, int caplen) +void NTP_Analyzer::DeliverPacket(int len, const u_char* data, bool is_orig, uint64 seq, const IP_Hdr* ip, int caplen) { Analyzer::DeliverPacket(len, data, is_orig, seq, ip, caplen); diff --git a/src/analyzer/protocol/ntp/NTP.h b/src/analyzer/protocol/ntp/NTP.h index 201c5a8774..87255fd2e4 100644 --- a/src/analyzer/protocol/ntp/NTP.h +++ b/src/analyzer/protocol/ntp/NTP.h @@ -46,7 +46,7 @@ public: protected: virtual void Done(); virtual void DeliverPacket(int len, const u_char* data, bool orig, - int seq, const IP_Hdr* ip, int caplen); + uint64 seq, const IP_Hdr* ip, int caplen); int Request(const u_char* data, int len); int Reply(const u_char* data, int len); diff --git a/src/analyzer/protocol/pia/PIA.cc b/src/analyzer/protocol/pia/PIA.cc index 388d1d501d..24d4565ce1 100644 --- a/src/analyzer/protocol/pia/PIA.cc +++ b/src/analyzer/protocol/pia/PIA.cc @@ -30,7 +30,7 @@ void PIA::ClearBuffer(Buffer* buffer) buffer->size = 0; } -void PIA::AddToBuffer(Buffer* buffer, int seq, int len, const u_char* data, +void PIA::AddToBuffer(Buffer* buffer, uint64 seq, int len, const u_char* data, bool is_orig) { u_char* tmp = 0; @@ -77,7 +77,7 @@ void PIA::PIA_Done() FinishEndpointMatcher(); } -void PIA::PIA_DeliverPacket(int len, const u_char* data, bool is_orig, int seq, +void PIA::PIA_DeliverPacket(int len, const u_char* data, bool is_orig, uint64 seq, const IP_Hdr* ip, int caplen) { if ( pkt_buffer.state == SKIPPING ) @@ -256,7 +256,7 @@ void PIA_TCP::DeliverStream(int len, const u_char* data, bool is_orig) stream_buffer.state = new_state; } -void PIA_TCP::Undelivered(int seq, int len, bool is_orig) +void PIA_TCP::Undelivered(uint64 seq, int len, bool is_orig) { tcp::TCP_ApplicationAnalyzer::Undelivered(seq, len, is_orig); @@ -337,8 +337,8 @@ void PIA_TCP::ActivateAnalyzer(analyzer::Tag tag, const Rule* rule) new tcp::TCP_Reassembler(this, tcp, tcp::TCP_Reassembler::Direct, tcp->Resp()); - int orig_seq = 0; - int resp_seq = 0; + uint64 orig_seq = 0; + uint64 resp_seq = 0; for ( DataBlock* b = pkt_buffer.head; b; b = b->next ) { diff --git a/src/analyzer/protocol/pia/PIA.h b/src/analyzer/protocol/pia/PIA.h index d8c272d219..db387769e8 100644 --- a/src/analyzer/protocol/pia/PIA.h +++ b/src/analyzer/protocol/pia/PIA.h @@ -42,7 +42,7 @@ public: protected: void PIA_Done(); void PIA_DeliverPacket(int len, const u_char* data, bool is_orig, - int seq, const IP_Hdr* ip, int caplen); + uint64 seq, const IP_Hdr* ip, int caplen); enum State { INIT, BUFFERING, MATCHING_ONLY, SKIPPING } state; @@ -52,7 +52,7 @@ protected: const u_char* data; bool is_orig; int len; - int seq; + uint64 seq; DataBlock* next; }; @@ -65,7 +65,7 @@ protected: State state; }; - void AddToBuffer(Buffer* buffer, int seq, int len, + void AddToBuffer(Buffer* buffer, uint64 seq, int len, const u_char* data, bool is_orig); void AddToBuffer(Buffer* buffer, int len, const u_char* data, bool is_orig); @@ -105,7 +105,7 @@ protected: } virtual void DeliverPacket(int len, const u_char* data, bool is_orig, - int seq, const IP_Hdr* ip, int caplen) + uint64 seq, const IP_Hdr* ip, int caplen) { Analyzer::DeliverPacket(len, data, is_orig, seq, ip, caplen); PIA_DeliverPacket(len, data, is_orig, seq, ip, caplen); @@ -150,14 +150,14 @@ protected: } virtual void DeliverPacket(int len, const u_char* data, bool is_orig, - int seq, const IP_Hdr* ip, int caplen) + uint64 seq, const IP_Hdr* ip, int caplen) { Analyzer::DeliverPacket(len, data, is_orig, seq, ip, caplen); PIA_DeliverPacket(len, data, is_orig, seq, ip, caplen); } virtual void DeliverStream(int len, const u_char* data, bool is_orig); - virtual void Undelivered(int seq, int len, bool is_orig); + virtual void Undelivered(uint64 seq, int len, bool is_orig); virtual void ActivateAnalyzer(analyzer::Tag tag, const Rule* rule = 0); diff --git a/src/analyzer/protocol/rpc/RPC.cc b/src/analyzer/protocol/rpc/RPC.cc index 1ffc7dd26e..38ed229a10 100644 --- a/src/analyzer/protocol/rpc/RPC.cc +++ b/src/analyzer/protocol/rpc/RPC.cc @@ -399,7 +399,7 @@ Contents_RPC::~Contents_RPC() { } -void Contents_RPC::Undelivered(int seq, int len, bool orig) +void Contents_RPC::Undelivered(uint64 seq, int len, bool orig) { tcp::TCP_SupportAnalyzer::Undelivered(seq, len, orig); NeedResync(); @@ -704,7 +704,7 @@ RPC_Analyzer::~RPC_Analyzer() } void RPC_Analyzer::DeliverPacket(int len, const u_char* data, bool orig, - int seq, const IP_Hdr* ip, int caplen) + uint64 seq, const IP_Hdr* ip, int caplen) { tcp::TCP_ApplicationAnalyzer::DeliverPacket(len, data, orig, seq, ip, caplen); len = min(len, caplen); diff --git a/src/analyzer/protocol/rpc/RPC.h b/src/analyzer/protocol/rpc/RPC.h index a705d272f6..e87f8afa95 100644 --- a/src/analyzer/protocol/rpc/RPC.h +++ b/src/analyzer/protocol/rpc/RPC.h @@ -203,7 +203,7 @@ protected: virtual void Init(); virtual bool CheckResync(int& len, const u_char*& data, bool orig); virtual void DeliverStream(int len, const u_char* data, bool orig); - virtual void Undelivered(int seq, int len, bool orig); + virtual void Undelivered(uint64 seq, int len, bool orig); virtual void NeedResync() { resync_state = NEED_RESYNC; @@ -234,7 +234,7 @@ public: protected: virtual void DeliverPacket(int len, const u_char* data, bool orig, - int seq, const IP_Hdr* ip, int caplen); + uint64 seq, const IP_Hdr* ip, int caplen); void ExpireTimer(double t); diff --git a/src/analyzer/protocol/smtp/SMTP.cc b/src/analyzer/protocol/smtp/SMTP.cc index c3fb21b6a4..c0e34ce6f1 100644 --- a/src/analyzer/protocol/smtp/SMTP.cc +++ b/src/analyzer/protocol/smtp/SMTP.cc @@ -76,14 +76,14 @@ void SMTP_Analyzer::Done() EndData(); } -void SMTP_Analyzer::Undelivered(int seq, int len, bool is_orig) +void SMTP_Analyzer::Undelivered(uint64 seq, int len, bool is_orig) { tcp::TCP_ApplicationAnalyzer::Undelivered(seq, len, is_orig); if ( len <= 0 ) return; - const char* buf = fmt("seq = %d, len = %d", seq, len); + const char* buf = fmt("seq = %"PRIu64", len = %d", seq, len); int buf_len = strlen(buf); Unexpected(is_orig, "content gap", buf_len, buf); diff --git a/src/analyzer/protocol/smtp/SMTP.h b/src/analyzer/protocol/smtp/SMTP.h index 8caaf846b8..da54814758 100644 --- a/src/analyzer/protocol/smtp/SMTP.h +++ b/src/analyzer/protocol/smtp/SMTP.h @@ -44,7 +44,7 @@ public: virtual void Done(); virtual void DeliverStream(int len, const u_char* data, bool orig); virtual void ConnectionFinished(int half_finished); - virtual void Undelivered(int seq, int len, bool orig); + virtual void Undelivered(uint64 seq, int len, bool orig); void SkipData() { skip_data = 1; } // skip delivery of data lines diff --git a/src/analyzer/protocol/snmp/SNMP.cc b/src/analyzer/protocol/snmp/SNMP.cc index bed2e3c12d..36282087fa 100644 --- a/src/analyzer/protocol/snmp/SNMP.cc +++ b/src/analyzer/protocol/snmp/SNMP.cc @@ -25,7 +25,7 @@ void SNMP_Analyzer::Done() } void SNMP_Analyzer::DeliverPacket(int len, const u_char* data, bool orig, - int seq, const IP_Hdr* ip, int caplen) + uint64 seq, const IP_Hdr* ip, int caplen) { Analyzer::DeliverPacket(len, data, orig, seq, ip, caplen); diff --git a/src/analyzer/protocol/snmp/SNMP.h b/src/analyzer/protocol/snmp/SNMP.h index 31f4450d9b..d01704d2ae 100644 --- a/src/analyzer/protocol/snmp/SNMP.h +++ b/src/analyzer/protocol/snmp/SNMP.h @@ -16,7 +16,7 @@ public: virtual void Done(); virtual void DeliverPacket(int len, const u_char* data, bool orig, - int seq, const IP_Hdr* ip, int caplen); + uint64 seq, const IP_Hdr* ip, int caplen); static analyzer::Analyzer* InstantiateAnalyzer(Connection* conn) { return new SNMP_Analyzer(conn); } diff --git a/src/analyzer/protocol/socks/SOCKS.cc b/src/analyzer/protocol/socks/SOCKS.cc index 76212d822b..e678528f35 100644 --- a/src/analyzer/protocol/socks/SOCKS.cc +++ b/src/analyzer/protocol/socks/SOCKS.cc @@ -86,7 +86,7 @@ void SOCKS_Analyzer::DeliverStream(int len, const u_char* data, bool orig) } } -void SOCKS_Analyzer::Undelivered(int seq, int len, bool orig) +void SOCKS_Analyzer::Undelivered(uint64 seq, int len, bool orig) { tcp::TCP_ApplicationAnalyzer::Undelivered(seq, len, orig); interp->NewGap(orig, len); diff --git a/src/analyzer/protocol/socks/SOCKS.h b/src/analyzer/protocol/socks/SOCKS.h index f005967fd8..2c72d507e6 100644 --- a/src/analyzer/protocol/socks/SOCKS.h +++ b/src/analyzer/protocol/socks/SOCKS.h @@ -23,7 +23,7 @@ public: virtual void Done(); virtual void DeliverStream(int len, const u_char* data, bool orig); - virtual void Undelivered(int seq, int len, bool orig); + virtual void Undelivered(uint64 seq, int len, bool orig); virtual void EndpointEOF(bool is_orig); static analyzer::Analyzer* InstantiateAnalyzer(Connection* conn) diff --git a/src/analyzer/protocol/ssl/SSL.cc b/src/analyzer/protocol/ssl/SSL.cc index 6cd2fa59f8..5e5d24888a 100644 --- a/src/analyzer/protocol/ssl/SSL.cc +++ b/src/analyzer/protocol/ssl/SSL.cc @@ -57,7 +57,7 @@ void SSL_Analyzer::DeliverStream(int len, const u_char* data, bool orig) } } -void SSL_Analyzer::Undelivered(int seq, int len, bool orig) +void SSL_Analyzer::Undelivered(uint64 seq, int len, bool orig) { tcp::TCP_ApplicationAnalyzer::Undelivered(seq, len, orig); had_gap = true; diff --git a/src/analyzer/protocol/ssl/SSL.h b/src/analyzer/protocol/ssl/SSL.h index f674d64fed..7748222dea 100644 --- a/src/analyzer/protocol/ssl/SSL.h +++ b/src/analyzer/protocol/ssl/SSL.h @@ -16,7 +16,7 @@ public: // Overriden from Analyzer. virtual void Done(); virtual void DeliverStream(int len, const u_char* data, bool orig); - virtual void Undelivered(int seq, int len, bool orig); + virtual void Undelivered(uint64 seq, int len, bool orig); // Overriden from tcp::TCP_ApplicationAnalyzer. virtual void EndpointEOF(bool is_orig); diff --git a/src/analyzer/protocol/stepping-stone/SteppingStone.cc b/src/analyzer/protocol/stepping-stone/SteppingStone.cc index 09a7444213..b6473dcf6e 100644 --- a/src/analyzer/protocol/stepping-stone/SteppingStone.cc +++ b/src/analyzer/protocol/stepping-stone/SteppingStone.cc @@ -63,7 +63,7 @@ void SteppingStoneEndpoint::Done() Event(stp_remove_endp, stp_id); } -int SteppingStoneEndpoint::DataSent(double t, int seq, int len, int caplen, +int SteppingStoneEndpoint::DataSent(double t, uint64 seq, int len, int caplen, const u_char* data, const IP_Hdr* /* ip */, const struct tcphdr* tp) { @@ -90,8 +90,8 @@ int SteppingStoneEndpoint::DataSent(double t, int seq, int len, int caplen, break; } - int ack = endp->AckSeq() - endp->StartSeq(); - int top_seq = seq + len; + uint64 ack = endp->ToRelativeSeqSpace(endp->AckSeq(), endp->AckWraps()); + uint64 top_seq = seq + len; if ( top_seq <= ack || top_seq <= stp_max_top_seq ) // There is no new data in this packet @@ -179,7 +179,7 @@ void SteppingStone_Analyzer::Init() } void SteppingStone_Analyzer::DeliverPacket(int len, const u_char* data, - bool is_orig, int seq, + bool is_orig, uint64 seq, const IP_Hdr* ip, int caplen) { tcp::TCP_ApplicationAnalyzer::DeliverPacket(len, data, is_orig, seq, diff --git a/src/analyzer/protocol/stepping-stone/SteppingStone.h b/src/analyzer/protocol/stepping-stone/SteppingStone.h index 1471c08a3b..518cd64a21 100644 --- a/src/analyzer/protocol/stepping-stone/SteppingStone.h +++ b/src/analyzer/protocol/stepping-stone/SteppingStone.h @@ -22,7 +22,7 @@ public: ~SteppingStoneEndpoint(); void Done(); - int DataSent(double t, int seq, int len, int caplen, const u_char* data, + int DataSent(double t, uint64 seq, int len, int caplen, const u_char* data, const IP_Hdr* ip, const struct tcphdr* tp); protected: @@ -30,7 +30,7 @@ protected: void CreateEndpEvent(int is_orig); tcp::TCP_Endpoint* endp; - int stp_max_top_seq; + uint64 stp_max_top_seq; double stp_last_time; double stp_resume_time; SteppingStoneManager* stp_manager; @@ -60,7 +60,7 @@ protected: // We support both packet and stream input and can be put in place even // if the TCP analyzer is not yet reassebmling. virtual void DeliverPacket(int len, const u_char* data, bool is_orig, - int seq, const IP_Hdr* ip, int caplen); + uint64 seq, const IP_Hdr* ip, int caplen); virtual void DeliverStream(int len, const u_char* data, bool is_orig); int orig_stream_pos; diff --git a/src/analyzer/protocol/syslog/Syslog.cc b/src/analyzer/protocol/syslog/Syslog.cc index 2b783afc64..5e5ce907e6 100644 --- a/src/analyzer/protocol/syslog/Syslog.cc +++ b/src/analyzer/protocol/syslog/Syslog.cc @@ -28,7 +28,7 @@ void Syslog_Analyzer::Done() Event(udp_session_done); } -void Syslog_Analyzer::DeliverPacket(int len, const u_char* data, bool orig, int seq, const IP_Hdr* ip, int caplen) +void Syslog_Analyzer::DeliverPacket(int len, const u_char* data, bool orig, uint64 seq, const IP_Hdr* ip, int caplen) { Analyzer::DeliverPacket(len, data, orig, seq, ip, caplen); interp->NewData(orig, data, data + len); @@ -88,7 +88,7 @@ void Syslog_Analyzer::DeliverPacket(int len, const u_char* data, bool orig, int // interp->NewData(orig, data, data + len); // } -//void Syslog_tcp::TCP_Analyzer::Undelivered(int seq, int len, bool orig) +//void Syslog_tcp::TCP_Analyzer::Undelivered(uint64 seq, int len, bool orig) // { // tcp::TCP_ApplicationAnalyzer::Undelivered(seq, len, orig); // interp->NewGap(orig, len); diff --git a/src/analyzer/protocol/syslog/Syslog.h b/src/analyzer/protocol/syslog/Syslog.h index 355863e36e..619ddb39ba 100644 --- a/src/analyzer/protocol/syslog/Syslog.h +++ b/src/analyzer/protocol/syslog/Syslog.h @@ -16,7 +16,7 @@ public: virtual void Done(); virtual void DeliverPacket(int len, const u_char* data, bool orig, - int seq, const IP_Hdr* ip, int caplen); + uint64 seq, const IP_Hdr* ip, int caplen); static analyzer::Analyzer* InstantiateAnalyzer(Connection* conn) { return new Syslog_Analyzer(conn); } @@ -38,7 +38,7 @@ protected: // // virtual void Done(); // virtual void DeliverStream(int len, const u_char* data, bool orig); -// virtual void Undelivered(int seq, int len, bool orig); +// virtual void Undelivered(uint64 seq, int len, bool orig); // virtual void EndpointEOF(tcp::TCP_Reassembler* endp); // // static analyzer::Analyzer* InstantiateAnalyzer(Connection* conn) diff --git a/src/analyzer/protocol/tcp/ContentLine.cc b/src/analyzer/protocol/tcp/ContentLine.cc index 63a3c07f00..72314dd45d 100644 --- a/src/analyzer/protocol/tcp/ContentLine.cc +++ b/src/analyzer/protocol/tcp/ContentLine.cc @@ -109,7 +109,7 @@ void ContentLine_Analyzer::DeliverStream(int len, const u_char* data, seq += len; } -void ContentLine_Analyzer::Undelivered(int seq, int len, bool orig) +void ContentLine_Analyzer::Undelivered(uint64 seq, int len, bool orig) { ForwardUndelivered(seq, len, orig); } diff --git a/src/analyzer/protocol/tcp/ContentLine.h b/src/analyzer/protocol/tcp/ContentLine.h index ecc1347984..93c473c47c 100644 --- a/src/analyzer/protocol/tcp/ContentLine.h +++ b/src/analyzer/protocol/tcp/ContentLine.h @@ -53,14 +53,14 @@ public: void SkipBytesAfterThisLine(int64_t length); void SkipBytes(int64_t length); - bool IsSkippedContents(int64_t seq, int64_t length) + bool IsSkippedContents(uint64_t seq, int64_t length) { return seq + length <= seq_to_skip; } protected: ContentLine_Analyzer(const char* name, Connection* conn, bool orig); virtual void DeliverStream(int len, const u_char* data, bool is_orig); - virtual void Undelivered(int seq, int len, bool orig); + virtual void Undelivered(uint64 seq, int len, bool orig); virtual void EndpointEOF(bool is_orig); class State; @@ -71,19 +71,19 @@ protected: void CheckNUL(); // Returns the sequence number delivered so far. - int64_t SeqDelivered() const { return seq_delivered_in_lines; } + uint64_t SeqDelivered() const { return seq_delivered_in_lines; } u_char* buf; // where we build up the body of the request int offset; // where we are in buf int buf_len; // how big buf is, total unsigned int last_char; // last (non-option) character scanned - int64_t seq; // last seq number - int64_t seq_to_skip; + uint64_t seq; // last seq number + uint64_t seq_to_skip; // Seq delivered up to through NewLine() -- it is adjusted // *before* NewLine() is called. - int64_t seq_delivered_in_lines; + uint64_t seq_delivered_in_lines; // Number of bytes to be skipped after this line. See // comments in SkipBytesAfterThisLine(). diff --git a/src/analyzer/protocol/tcp/TCP.cc b/src/analyzer/protocol/tcp/TCP.cc index c422d01f32..f9fb0fb2b7 100644 --- a/src/analyzer/protocol/tcp/TCP.cc +++ b/src/analyzer/protocol/tcp/TCP.cc @@ -36,1088 +36,8 @@ namespace { // local namespace static const int ORIG = 1; static const int RESP = 2; -TCP_Analyzer::TCP_Analyzer(Connection* conn) -: TransportLayerAnalyzer("TCP", conn) - { - // Set a timer to eventually time out this connection. - ADD_ANALYZER_TIMER(&TCP_Analyzer::ExpireTimer, - network_time + tcp_SYN_timeout, 0, - TIMER_TCP_EXPIRE); - - deferred_gen_event = close_deferred = 0; - - seen_first_ACK = 0; - is_active = 1; - finished = 0; - reassembling = 0; - first_packet_seen = 0; - is_partial = 0; - - orig = new TCP_Endpoint(this, 1); - resp = new TCP_Endpoint(this, 0); - - orig->SetPeer(resp); - resp->SetPeer(orig); - } - -TCP_Analyzer::~TCP_Analyzer() - { - LOOP_OVER_GIVEN_CHILDREN(i, packet_children) - delete *i; - - delete orig; - delete resp; - } - -void TCP_Analyzer::Init() - { - Analyzer::Init(); - LOOP_OVER_GIVEN_CHILDREN(i, packet_children) - (*i)->Init(); - } - -void TCP_Analyzer::Done() - { - Analyzer::Done(); - - if ( connection_pending && is_active && ! BothClosed() ) - Event(connection_pending); - - LOOP_OVER_GIVEN_CHILDREN(i, packet_children) - (*i)->Done(); - - orig->Done(); - resp->Done(); - - finished = 1; - } - -void TCP_Analyzer::EnableReassembly() - { - SetReassembler(new TCP_Reassembler(this, this, - TCP_Reassembler::Forward, orig), - new TCP_Reassembler(this, this, - TCP_Reassembler::Forward, resp)); - - reassembling = 1; - - if ( new_connection_contents ) - Event(new_connection_contents); - } - -void TCP_Analyzer::SetReassembler(TCP_Reassembler* rorig, - TCP_Reassembler* rresp) - { - orig->AddReassembler(rorig); - rorig->SetDstAnalyzer(this); - resp->AddReassembler(rresp); - rresp->SetDstAnalyzer(this); - - reassembling = 1; - - if ( new_connection_contents ) - Event(new_connection_contents); - } - -const struct tcphdr* TCP_Analyzer::ExtractTCP_Header(const u_char*& data, - int& len, int& caplen) - { - const struct tcphdr* tp = (const struct tcphdr*) data; - uint32 tcp_hdr_len = tp->th_off * 4; - - if ( tcp_hdr_len < sizeof(struct tcphdr) ) - { - Weird("bad_TCP_header_len"); - return 0; - } - - if ( tcp_hdr_len > uint32(len) || - sizeof(struct tcphdr) > uint32(caplen) ) - { - // This can happen even with the above test, due to TCP - // options. - Weird("truncated_header"); - return 0; - } - - len -= tcp_hdr_len; // remove TCP header - caplen -= tcp_hdr_len; - data += tcp_hdr_len; - - return tp; - } - -bool TCP_Analyzer::ValidateChecksum(const struct tcphdr* tp, - TCP_Endpoint* endpoint, int len, int caplen) - { - if ( ! ignore_checksums && caplen >= len && - ! endpoint->ValidChecksum(tp, len) ) - { - Weird("bad_TCP_checksum"); - endpoint->CheckHistory(HIST_CORRUPT_PKT, 'C'); - return false; - } - else - return true; - } - -void TCP_Analyzer::CheckFlagCombos(TCP_Flags flags, TCP_Endpoint* endpoint, - uint32 base_seq, int len, int dst_port) - { - bool is_orig = endpoint->IsOrig(); - - if ( is_orig && ! (first_packet_seen & ORIG) ) - is_partial = ! flags.SYN() || flags.ACK(); - - if ( ! is_orig && ! (first_packet_seen & RESP) && ! is_partial ) - is_partial = ! flags.SYN(); - - int bits_set = (flags.SYN() ? 1 : 0) + (flags.FIN() ? 1 : 0) + - (flags.RST() ? 1 : 0); - if ( bits_set > 1 ) - { - if ( flags.FIN() && flags.RST() ) - endpoint->CheckHistory(HIST_FIN_RST_PKT, 'I'); - else - endpoint->CheckHistory(HIST_MULTI_FLAG_PKT, 'Q'); - } - - else if ( bits_set == 1 ) - { - if ( flags.SYN() ) - { - char code = flags.ACK() ? 'H' : 'S'; - - if ( endpoint->CheckHistory(HIST_SYN_PKT, code) && - base_seq != endpoint->hist_last_SYN ) - endpoint->AddHistory(code); - - endpoint->hist_last_SYN = base_seq; - } - - if ( flags.FIN() ) - { - // For FIN's, the sequence number comes at the - // end of (any data in) the packet, not the - // beginning as for SYNs and RSTs. - if ( endpoint->CheckHistory(HIST_FIN_PKT, 'F') && - base_seq + len != endpoint->hist_last_FIN ) - endpoint->AddHistory('F'); - - endpoint->hist_last_FIN = base_seq + len; - } - - if ( flags.RST() ) - { - if ( endpoint->CheckHistory(HIST_RST_PKT, 'R') && - base_seq != endpoint->hist_last_RST ) - endpoint->AddHistory('R'); - - endpoint->hist_last_RST = base_seq; - } - } - - else - { // bits_set == 0 - if ( len ) - endpoint->CheckHistory(HIST_DATA_PKT, 'D'); - - else if ( flags.ACK() ) - endpoint->CheckHistory(HIST_ACK_PKT, 'A'); - } - } - -void TCP_Analyzer::UpdateWindow(TCP_Endpoint* endpoint, unsigned int window, - uint32 base_seq, uint32 ack_seq, - TCP_Flags flags) - { - // Note, the offered window on an initial SYN is unscaled, even - // if the SYN includes scaling, so we need to do the following - // test *before* updating the scaling information below. (Hmmm, - // how does this work for windows on SYN/ACKs? ###) - int scale = endpoint->window_scale; - window = window << scale; - - // Don't analyze window values off of SYNs, they're sometimes - // immediately rescinded. - if ( ! flags.SYN() ) - { - // ### Decide whether to accept new window based on Active - // Mapping policy. - if ( int(base_seq - endpoint->window_seq) >= 0 && - int(ack_seq - endpoint->window_ack_seq) >= 0 ) - { - uint32 new_edge = ack_seq + window; - uint32 old_edge = endpoint->window_ack_seq + endpoint->window; - int advance = new_edge - old_edge; - - if ( advance < 0 ) - { - // A window recision. We don't report these - // for FINs or RSTs, or if the connection - // has already been partially closed, since - // such recisions occur frequently in practice, - // probably as the receiver loses buffer memory - // due to its process going away. - // - // We also, for window scaling, allow a bit - // of slop ###. This is because sometimes - // there will be an apparent recision due - // to the granularity of the scaling. - if ( ! flags.FIN() && ! flags.RST() && - endpoint->state != TCP_ENDPOINT_CLOSED && - endpoint->state != TCP_ENDPOINT_RESET && - (-advance) >= (1 << scale) ) - Weird("window_recision"); - } - - endpoint->window = window; - endpoint->window_ack_seq = ack_seq; - endpoint->window_seq = base_seq; - } - } - } - -void TCP_Analyzer::ProcessSYN(const IP_Hdr* ip, const struct tcphdr* tp, - uint32 tcp_hdr_len, int& seq_len, - TCP_Endpoint* endpoint, TCP_Endpoint* peer, - uint32 base_seq, uint32 ack_seq, - const IPAddr& orig_addr, - int is_orig, TCP_Flags flags) - { - int len = seq_len; - - ++seq_len; // SYN consumes a byte of sequence space - - if ( flags.RST() ) - Weird("TCP_christmas"); - - if ( flags.URG() ) - Weird("baroque_SYN"); - - if ( len > 0 ) - // T/TCP definitely complicates this. - Weird("SYN_with_data"); - - RecordVal* SYN_vals = BuildSYNPacketVal(is_orig, ip, tp)->AsRecordVal(); - - // ### In the following, we could be fooled by an - // inconsistent SYN retransmission. Where's a normalizer - // when you need one? - - // ### We know that field 5 is the window scaling .... - int scale = int(SYN_vals->Lookup(5)->CoerceToInt()); - - if ( scale < 0 ) - { // no window scaling option - if ( flags.ACK() ) - { // window scaling not negotiated - endpoint->window_scale = 0; - peer->window_scale = 0; - } - else - // We're not offering window scaling. - // Ideally, we'd remember this fact so that - // if the SYN/ACK *does* include window - // scaling, we know it won't be negotiated. - // But it's a pain to track that, and hard - // to see how an adversarial responder could - // use it to evade. Also, if we *do* want - // to track it, we could do so using - // connection_SYN_packet. - endpoint->window_scale = 0; - } - else - { - endpoint->window_scale = scale; - endpoint->window_seq = base_seq; - endpoint->window_ack_seq = ack_seq; - - peer->window_seq = ack_seq; - peer->window_ack_seq = base_seq; - } - - if ( connection_SYN_packet ) - { - val_list* vl = new val_list; - vl->append(BuildConnVal()); - vl->append(SYN_vals); - ConnectionEvent(connection_SYN_packet, vl); - } - else - Unref(SYN_vals); - - // Passive fingerprinting. - // - // is_orig will be removed once we can do SYN-ACK fingerprinting. - if ( OS_version_found && is_orig ) - { - AddrVal src_addr_val(orig_addr); - if ( generate_OS_version_event->Size() == 0 || - generate_OS_version_event->Lookup(&src_addr_val) ) - { - RecordVal* OS_val = - BuildOSVal(is_orig, ip, tp, tcp_hdr_len); - if ( OS_val ) - { // found new OS version - val_list* vl = new val_list; - vl->append(BuildConnVal()); - vl->append(new AddrVal(orig_addr)); - vl->append(OS_val); - ConnectionEvent(OS_version_found, vl); - } - } - } - } - -void TCP_Analyzer::ProcessFIN(double t, TCP_Endpoint* endpoint, - int& seq_len, uint32 base_seq) - { - ++seq_len; // FIN consumes a byte of sequence space. - ++endpoint->FIN_cnt; // remember that we've seen a FIN - - if ( t < endpoint->last_time + tcp_storm_interarrival_thresh && - endpoint->FIN_cnt == tcp_storm_thresh ) - Weird("FIN_storm"); - - // Remember the relative seq in FIN_seq. - endpoint->FIN_seq = base_seq - endpoint->StartSeq() + seq_len; - } - -void TCP_Analyzer::ProcessRST(double t, TCP_Endpoint* endpoint, - const IP_Hdr* ip, uint32 base_seq, - int len, int& seq_len) - { - if ( t < endpoint->last_time + tcp_storm_interarrival_thresh && - ++endpoint->RST_cnt == tcp_storm_thresh ) - Weird("RST_storm"); - - else if ( endpoint->RST_cnt == 0 ) - ++endpoint->RST_cnt; // Remember we've seen a RST - - if ( len > 0 ) - { - // This now happens often enough that it's - // not in the least interesting. - // Weird("RST_with_data"); - - // Don't include the data in the computation of - // the sequence space for this connection, as - // it's not in fact part of the TCP stream. - seq_len = 0; - } - - PacketWithRST(); - } - -void TCP_Analyzer::ProcessFlags(double t, - const IP_Hdr* ip, const struct tcphdr* tp, - uint32 tcp_hdr_len, int len, int& seq_len, - TCP_Endpoint* endpoint, TCP_Endpoint* peer, - uint32 base_seq, uint32 ack_seq, - const IPAddr& orig_addr, - int is_orig, TCP_Flags flags) - { - if ( flags.SYN() ) - ProcessSYN(ip, tp, tcp_hdr_len, seq_len, endpoint, peer, - base_seq, ack_seq, orig_addr, is_orig, flags); - - if ( flags.FIN() ) - ProcessFIN(t, endpoint, seq_len, base_seq); - - if ( flags.RST() ) - ProcessRST(t, endpoint, ip, base_seq, len, seq_len); - - if ( flags.ACK() ) - ProcessACK(endpoint, peer, ack_seq, is_orig, flags); - } - -void TCP_Analyzer::TransitionFromInactive(double t, TCP_Endpoint* endpoint, - uint32 base_seq, - uint32 last_seq, int SYN) - { - if ( SYN ) - { - // ## endpoint->AckSeq() = endpoint->start_seq = base_seq; - endpoint->InitAckSeq(base_seq); - endpoint->InitStartSeq(base_seq); - } - else - { - // This is a partial connection - set up the - // initial sequence numbers as though we saw - // a SYN, to keep the relative byte numbering - // consistent. - // ## endpoint->AckSeq() = endpoint->start_seq = base_seq - 1; - endpoint->InitAckSeq(base_seq - 1); - endpoint->InitStartSeq(base_seq - 1); - } - - // ## endpoint->last_seq = last_seq; - endpoint->InitLastSeq(last_seq); - endpoint->start_time = t; - } - -int TCP_Analyzer::UpdateLastSeq(TCP_Endpoint* endpoint, uint32 last_seq, - TCP_Flags flags) - { - int delta_last = seq_delta(last_seq, endpoint->LastSeq()); - - if ( (flags.SYN() || flags.RST()) && - (delta_last > TOO_LARGE_SEQ_DELTA || - delta_last < -TOO_LARGE_SEQ_DELTA) ) - // ### perhaps trust RST seq #'s if initial and not too - // outlandish, but not if they're coming after the other - // side has sent a FIN - trust the FIN ack instead - ; - - else if ( flags.FIN() && - endpoint->LastSeq() == endpoint->StartSeq() + 1 ) - // Update last_seq based on the FIN even if delta_last < 0. - // This is to accommodate > 2 GB connections for which - // we've only seen the SYN and the FIN (hence the check - // for last_seq == start_seq + 1). - endpoint->UpdateLastSeq(last_seq); - - else if ( endpoint->state == TCP_ENDPOINT_RESET ) - // don't trust any subsequent sequence numbers - ; - - else if ( delta_last > 0 ) - // ### check for large jumps here. - // ## endpoint->last_seq = last_seq; - endpoint->UpdateLastSeq(last_seq); - - else if ( delta_last <= 0 ) - { // ### ++retransmit, unless this is a pure ack - } - - return delta_last; - } - -void TCP_Analyzer::ProcessACK(TCP_Endpoint* endpoint, TCP_Endpoint* peer, - uint32 ack_seq, int is_orig, - TCP_Flags flags) - { - if ( is_orig && ! seen_first_ACK && - (endpoint->state == TCP_ENDPOINT_ESTABLISHED || - endpoint->state == TCP_ENDPOINT_SYN_SENT) ) - { - seen_first_ACK = 1; - Event(connection_first_ACK); - } - - if ( peer->state == TCP_ENDPOINT_INACTIVE ) - { - if ( ! flags.SYN() && ! flags.FIN() && ! flags.RST() ) - { - if ( endpoint->state == TCP_ENDPOINT_SYN_SENT || - endpoint->state == TCP_ENDPOINT_SYN_ACK_SENT || - endpoint->state == TCP_ENDPOINT_ESTABLISHED ) - { - // We've already sent a SYN, but that - // hasn't roused the other end, yet we're - // ack'ing their data. - - if ( ! Conn()->DidWeird() ) - Weird("possible_split_routing"); - } - } - - // Start the sequence numbering as if there was an initial - // SYN, so the relative numbering of subsequent data packets - // stays consistent. - // ## peer->start_seq = peer->AckSeq() = peer->last_seq = - // ## ack_seq - 1; - peer->InitStartSeq(ack_seq - 1); - peer->InitAckSeq(ack_seq - 1); - peer->InitLastSeq(ack_seq - 1); - } - - else if ( ! flags.RST() ) - { // don't trust ack's in RST packets - int delta_ack = seq_delta(ack_seq, peer->AckSeq()); - if ( ack_seq == 0 && delta_ack > TOO_LARGE_SEQ_DELTA ) - // More likely that this is a broken ack than a - // large connection that happens to land on 0 in the - // sequence space. - ; - - else if ( delta_ack > 0 ) - peer->UpdateAckSeq(ack_seq); - } - - peer->AckReceived(ack_seq - peer->StartSeq()); - } - -void TCP_Analyzer::UpdateInactiveState(double t, - TCP_Endpoint* endpoint, TCP_Endpoint* peer, - uint32 base_seq, uint32 ack_seq, - int len, int is_orig, TCP_Flags flags, - int& do_close, int& gen_event) - { - if ( flags.SYN() ) - { - if ( is_orig ) - { - if ( flags.ACK() ) - { - Weird("connection_originator_SYN_ack"); - endpoint->SetState(TCP_ENDPOINT_SYN_ACK_SENT); - } - else - endpoint->SetState(TCP_ENDPOINT_SYN_SENT); - - if ( tcp_attempt_delay ) - ADD_ANALYZER_TIMER(&TCP_Analyzer::AttemptTimer, - t + tcp_attempt_delay, 1, - TIMER_TCP_ATTEMPT); - } - else - { - if ( flags.ACK() ) - { - if ( peer->state != TCP_ENDPOINT_INACTIVE && - peer->state != TCP_ENDPOINT_PARTIAL && - ! seq_between(ack_seq, peer->StartSeq(), peer->LastSeq()) ) - Weird("bad_SYN_ack"); - } - - else if ( peer->state == TCP_ENDPOINT_SYN_ACK_SENT && - base_seq == endpoint->StartSeq() ) - { - // This is a SYN/SYN-ACK reversal, - // per the discussion in IsReuse. - // Flip the endpoints and establish - // the connection. - is_partial = 0; - Conn()->FlipRoles(); - peer->SetState(TCP_ENDPOINT_ESTABLISHED); - } - - else - Weird("simultaneous_open"); - - if ( peer->state == TCP_ENDPOINT_SYN_SENT ) - peer->SetState(TCP_ENDPOINT_ESTABLISHED); - else if ( peer->state == TCP_ENDPOINT_INACTIVE ) - { - // If we were to ignore SYNs and - // only instantiate state on SYN - // acks, then we'd do: - // peer->SetState(TCP_ENDPOINT_ESTABLISHED); - // here. - Weird("unsolicited_SYN_response"); - } - - endpoint->SetState(TCP_ENDPOINT_ESTABLISHED); - - if ( peer->state != TCP_ENDPOINT_PARTIAL ) - { - Event(connection_established); - Conn()->EnableStatusUpdateTimer(); - } - } - } - - if ( flags.FIN() ) - { - endpoint->SetState(TCP_ENDPOINT_CLOSED); - do_close = gen_event = 1; - if ( peer->state != TCP_ENDPOINT_PARTIAL && ! flags.SYN() ) - Weird("spontaneous_FIN"); - } - - if ( flags.RST() ) - { - endpoint->SetState(TCP_ENDPOINT_RESET); - - int is_reject = 0; - - if ( is_orig ) - { - // If our peer is established then we saw - // a SYN-ack but not SYN - so a reverse - // scan, and we should treat this as a - // reject. - if ( peer->state == TCP_ENDPOINT_ESTABLISHED ) - is_reject = 1; - } - - else if ( peer->state == TCP_ENDPOINT_SYN_SENT || - peer->state == TCP_ENDPOINT_SYN_ACK_SENT ) - // We're rejecting an initial SYN. - is_reject = 1; - - do_close = 1; - gen_event = ! is_reject; - - if ( is_reject ) - Event(connection_rejected); - - else if ( peer->state == TCP_ENDPOINT_INACTIVE ) - Weird("spontaneous_RST"); - } - - if ( endpoint->state == TCP_ENDPOINT_INACTIVE ) - { // No control flags to change the state. - if ( ! is_orig && len == 0 && - orig->state == TCP_ENDPOINT_SYN_SENT ) - // Some eccentric TCP's will ack an initial - // SYN prior to sending a SYN reply (hello, - // ftp.microsoft.com). For those, don't - // consider the ack as forming a partial - // connection. - ; - else - { - endpoint->SetState(TCP_ENDPOINT_PARTIAL); - Conn()->EnableStatusUpdateTimer(); - - if ( peer->state == TCP_ENDPOINT_PARTIAL ) - // We've seen both sides of a partial - // connection, report it. - Event(partial_connection); - } - } - } - -void TCP_Analyzer::UpdateSYN_SentState(double t, - TCP_Endpoint* endpoint, TCP_Endpoint* peer, - uint32 base_seq, uint32 last_seq, - int len, int is_orig, TCP_Flags flags, - int& do_close, int& gen_event) - { - if ( flags.SYN() ) - { - if ( is_orig ) - { - if ( flags.ACK() && ! flags.FIN() && ! flags.RST() && - endpoint->state != TCP_ENDPOINT_SYN_ACK_SENT ) - Weird("repeated_SYN_with_ack"); - } - else - { - if ( ! flags.ACK() && - endpoint->state != TCP_ENDPOINT_SYN_SENT ) - Weird("repeated_SYN_reply_wo_ack"); - } - - if ( base_seq != endpoint->StartSeq() ) - { - Weird("SYN_seq_jump"); - // ## endpoint->AckSeq() = endpoint->start_seq = base_seq; - // ## endpoint->last_seq = last_seq; - endpoint->InitStartSeq(base_seq); - endpoint->InitAckSeq(base_seq); - endpoint->InitLastSeq(last_seq); - } - } - - if ( flags.FIN() ) - { - if ( peer->state == TCP_ENDPOINT_INACTIVE || - peer->state == TCP_ENDPOINT_SYN_SENT ) - Weird("inappropriate_FIN"); - - endpoint->SetState(TCP_ENDPOINT_CLOSED); - do_close = gen_event = 1; - } - - if ( flags.RST() ) - { - endpoint->SetState(TCP_ENDPOINT_RESET); - ConnectionReset(); - do_close = 1; - } - - else if ( len > 0 ) - Weird("data_before_established"); - } - -void TCP_Analyzer::UpdateEstablishedState(double t, - TCP_Endpoint* endpoint, TCP_Endpoint* peer, - uint32 base_seq, uint32 last_seq, - int is_orig, TCP_Flags flags, - int& do_close, int& gen_event) - { - if ( flags.SYN() ) - { - if ( endpoint->state == TCP_ENDPOINT_PARTIAL && - peer->state == TCP_ENDPOINT_INACTIVE && ! flags.ACK() ) - { - Weird("SYN_after_partial"); - endpoint->SetState(TCP_ENDPOINT_SYN_SENT); - } - - if ( endpoint->Size() > 0 ) - Weird("SYN_inside_connection"); - - if ( base_seq != endpoint->StartSeq() ) - Weird("SYN_seq_jump"); - - // Make a guess that somehow the connection didn't - // get established, and this SYN will be the - // one that actually sets it up. - // ## endpoint->AckSeq() = endpoint->start_seq = base_seq; - // ## endpoint->last_seq = last_seq; - endpoint->InitStartSeq(base_seq); - endpoint->InitAckSeq(base_seq); - endpoint->InitLastSeq(last_seq); - } - - if ( flags.FIN() && ! flags.RST() ) // ### - { // should check sequence/ack numbers here ### - endpoint->SetState(TCP_ENDPOINT_CLOSED); - - if ( peer->state == TCP_ENDPOINT_RESET && - peer->prev_state == TCP_ENDPOINT_CLOSED ) - // The peer sent a FIN followed by a RST. - // Turn it back into CLOSED state, because - // this was actually normal termination. - peer->SetState(TCP_ENDPOINT_CLOSED); - - do_close = gen_event = 1; - } - - if ( flags.RST() ) - { - endpoint->SetState(TCP_ENDPOINT_RESET); - do_close = 1; - - if ( peer->state != TCP_ENDPOINT_RESET || - peer->prev_state != TCP_ENDPOINT_ESTABLISHED ) - ConnectionReset(); - } - } - -void TCP_Analyzer::UpdateClosedState(double t, TCP_Endpoint* endpoint, - int delta_last, TCP_Flags flags, int& do_close) - { - if ( flags.SYN() ) - Weird("SYN_after_close"); - - if ( flags.FIN() && delta_last > 0 ) - // Probably should also complain on FIN recision. - // That requires an extra state variable to avoid - // generating slews of weird's when a TCP gets - // seriously confused (this from experience). - Weird("FIN_advanced_last_seq"); - - // Previously, our state was CLOSED, since we sent a FIN. - // If our peer was also closed, then don't change our state - // now on a RST, since this connection has already seen a FIN - // exchange. - if ( flags.RST() && endpoint->peer->state != TCP_ENDPOINT_CLOSED ) - { - endpoint->SetState(TCP_ENDPOINT_RESET); - - if ( ! endpoint->did_close ) - // RST after FIN. - do_close = 1; - - if ( connection_reset ) - ADD_ANALYZER_TIMER(&TCP_Analyzer::ResetTimer, - t + tcp_reset_delay, 1, - TIMER_TCP_RESET); - } - } - -void TCP_Analyzer::UpdateResetState(int len, TCP_Flags flags, - TCP_Endpoint* endpoint, uint32 base_seq, - uint32 last_seq) - { - if ( flags.SYN() ) - { - Weird("SYN_after_reset"); - - if ( endpoint->prev_state == TCP_ENDPOINT_INACTIVE ) - { - // Seq. numbers were initialized by a RST packet from this endpoint, - // but now that a SYN is seen from it, that could mean the earlier - // RST was spoofed/injected, so re-initialize. This mostly just - // helps prevent misrepresentations of payload sizes that are based - // on bad initial sequence values. - endpoint->InitStartSeq(base_seq); - endpoint->InitAckSeq(base_seq); - endpoint->InitLastSeq(last_seq); - } - } - - if ( flags.FIN() ) - Weird("FIN_after_reset"); - - if ( len > 0 && ! flags.RST() ) - Weird("data_after_reset"); - } - -void TCP_Analyzer::UpdateStateMachine(double t, - TCP_Endpoint* endpoint, TCP_Endpoint* peer, - uint32 base_seq, uint32 ack_seq, uint32 last_seq, - int len, int delta_last, int is_orig, TCP_Flags flags, - int& do_close, int& gen_event) - { - do_close = 0; // whether to report the connection as closed - gen_event = 0; // if so, whether to generate an event - - switch ( endpoint->state ) { - - case TCP_ENDPOINT_INACTIVE: - UpdateInactiveState(t, endpoint, peer, base_seq, ack_seq, - len, is_orig, flags, - do_close, gen_event); - break; - - case TCP_ENDPOINT_SYN_SENT: - case TCP_ENDPOINT_SYN_ACK_SENT: - UpdateSYN_SentState(t, endpoint, peer, base_seq, last_seq, - len, is_orig, flags, - do_close, gen_event); - break; - - case TCP_ENDPOINT_ESTABLISHED: - case TCP_ENDPOINT_PARTIAL: - UpdateEstablishedState(t, endpoint, peer, base_seq, last_seq, - is_orig, flags, do_close, gen_event); - break; - - case TCP_ENDPOINT_CLOSED: - UpdateClosedState(t, endpoint, delta_last, flags, do_close); - break; - - case TCP_ENDPOINT_RESET: - UpdateResetState(len, flags, endpoint, base_seq, last_seq); - break; - } - } - -void TCP_Analyzer::GeneratePacketEvent(TCP_Endpoint* endpoint, - TCP_Endpoint* peer, - uint32 base_seq, uint32 ack_seq, - const u_char* data, int len, int caplen, - int is_orig, TCP_Flags flags) - { - char tcp_flags[256]; - int tcp_flag_len = 0; - - if ( flags.SYN() ) tcp_flags[tcp_flag_len++] = 'S'; - if ( flags.FIN() ) tcp_flags[tcp_flag_len++] = 'F'; - if ( flags.RST() ) tcp_flags[tcp_flag_len++] = 'R'; - if ( flags.ACK() ) tcp_flags[tcp_flag_len++] = 'A'; - if ( flags.PUSH() ) tcp_flags[tcp_flag_len++] = 'P'; - if ( flags.URG() ) tcp_flags[tcp_flag_len++] = 'U'; - - tcp_flags[tcp_flag_len] = '\0'; - - val_list* vl = new val_list(); - - vl->append(BuildConnVal()); - vl->append(new Val(is_orig, TYPE_BOOL)); - vl->append(new StringVal(tcp_flags)); - vl->append(new Val(base_seq - endpoint->StartSeq(), TYPE_COUNT)); - vl->append(new Val(flags.ACK() ? - ack_seq - peer->StartSeq() : 0, TYPE_COUNT)); - vl->append(new Val(len, TYPE_COUNT)); - - // We need the min() here because Ethernet padding can lead to - // caplen > len. - vl->append(new StringVal(min(caplen, len), (const char*) data)); - - ConnectionEvent(tcp_packet, vl); - } - -int TCP_Analyzer::DeliverData(double t, const u_char* data, int len, int caplen, - const IP_Hdr* ip, const struct tcphdr* tp, - TCP_Endpoint* endpoint, uint32 base_seq, - int is_orig, TCP_Flags flags) - { - int data_seq = base_seq - endpoint->StartSeq(); - if ( flags.SYN() ) - ++data_seq; // skip over SYN octet - - int need_contents = endpoint->DataSent(t, data_seq, - len, caplen, data, ip, tp); - - return need_contents; - } - -void TCP_Analyzer::CheckRecording(int need_contents, TCP_Flags flags) - { - bool record_current_content = need_contents || Conn()->RecordContents(); - bool record_current_packet = - Conn()->RecordPackets() || - flags.SYN() || flags.FIN() || flags.RST(); - - Conn()->SetRecordCurrentContent(record_current_content); - Conn()->SetRecordCurrentPacket(record_current_packet); - } - -void TCP_Analyzer::CheckPIA_FirstPacket(int is_orig, const IP_Hdr* ip) - { - if ( is_orig && ! (first_packet_seen & ORIG) ) - { - pia::PIA_TCP* pia = static_cast(Conn()->GetPrimaryPIA()); - if ( pia ) - pia->FirstPacket(is_orig, ip); - first_packet_seen |= ORIG; - } - - if ( ! is_orig && ! (first_packet_seen & RESP) ) - { - pia::PIA_TCP* pia = static_cast(Conn()->GetPrimaryPIA()); - if ( pia ) - pia->FirstPacket(is_orig, ip); - first_packet_seen |= RESP; - } - } - -void TCP_Analyzer::DeliverPacket(int len, const u_char* data, bool is_orig, - int seq, const IP_Hdr* ip, int caplen) - { - TransportLayerAnalyzer::DeliverPacket(len, data, orig, seq, ip, caplen); - - const struct tcphdr* tp = ExtractTCP_Header(data, len, caplen); - if ( ! tp ) - return; - - // We need the min() here because Ethernet frame padding can lead to - // caplen > len. - if ( packet_contents ) - PacketContents(data, min(len, caplen)); - - TCP_Endpoint* endpoint = is_orig ? orig : resp; - TCP_Endpoint* peer = endpoint->peer; - - if ( ! ValidateChecksum(tp, endpoint, len, caplen) ) - return; - - TCP_Flags flags(tp); - - uint32 base_seq = ntohl(tp->th_seq); - uint32 ack_seq = ntohl(tp->th_ack); - - CheckFlagCombos(flags, endpoint, base_seq, len, ntohs(tp->th_dport)); - - UpdateWindow(endpoint, ntohs(tp->th_win), base_seq, ack_seq, flags); - - double t = current_timestamp; - - if ( ! orig->did_close || ! resp->did_close ) - Conn()->SetLastTime(t); - - const IPAddr orig_addr = Conn()->OrigAddr(); - - uint32 tcp_hdr_len = data - (const u_char*) tp; - - int seq_len = len; // length in terms of sequence space - - ProcessFlags(t, ip, tp, tcp_hdr_len, len, seq_len, endpoint, peer, base_seq, - ack_seq, orig_addr, is_orig, flags); - - uint32 last_seq = base_seq + seq_len; - - if ( endpoint->state == TCP_ENDPOINT_INACTIVE ) - TransitionFromInactive(t, endpoint, base_seq, last_seq, - flags.SYN()); - - int delta_last = UpdateLastSeq(endpoint, last_seq, flags); - - endpoint->last_time = t; - - int do_close; - int gen_event; - UpdateStateMachine(t, endpoint, peer, base_seq, ack_seq, last_seq, - len, delta_last, is_orig, flags, - do_close, gen_event); - - if ( tcp_packet ) - GeneratePacketEvent(endpoint, peer, base_seq, ack_seq, - data, len, caplen, is_orig, flags); - - if ( tcp_option && tcp_hdr_len > sizeof(*tp) && - tcp_hdr_len <= uint32(caplen) ) - ParseTCPOptions(tp, TCPOptionEvent, this, is_orig, 0); - - if ( DEBUG_tcp_data_sent ) - { - DEBUG_MSG("%.6f before DataSent: len=%d caplen=%d skip=%d\n", - network_time, len, caplen, Skipping()); - } - - int need_contents = 0; - if ( len > 0 && (caplen >= len || packet_children.size()) && - ! flags.RST() && ! Skipping() ) - need_contents = DeliverData(t, data, len, caplen, ip, tp, - endpoint, base_seq, - is_orig, flags); - - endpoint->CheckEOF(); - - if ( do_close ) - { - // We need to postpone doing this until after we process - // DataSent, so we don't generate a connection_finished event - // until after data perhaps included with the FIN is processed. - ConnectionClosed(endpoint, peer, gen_event); - } - - CheckRecording(need_contents, flags); - - // Handle child_packet analyzers. Note: This happens *after* the - // packet has been processed and the TCP state updated. - LOOP_OVER_GIVEN_CHILDREN(i, packet_children) - (*i)->NextPacket(len, data, is_orig, - base_seq - endpoint->StartSeq(), ip, caplen); - - if ( ! reassembling ) - ForwardPacket(len, data, is_orig, - base_seq - endpoint->StartSeq(), ip, caplen); - - CheckPIA_FirstPacket(is_orig, ip); - } - -void TCP_Analyzer::DeliverStream(int len, const u_char* data, bool orig) - { - Analyzer::DeliverStream(len, data, orig); - } - -void TCP_Analyzer::Undelivered(int seq, int len, bool is_orig) - { - Analyzer::Undelivered(seq, len, orig); - } - -void TCP_Analyzer::FlipRoles() - { - Analyzer::FlipRoles(); - - sessions->tcp_stats.FlipState(orig->state, resp->state); - TCP_Endpoint* tmp_ep = resp; - resp = orig; - orig = tmp_ep; - orig->is_orig = !orig->is_orig; - resp->is_orig = !resp->is_orig; - } - -void TCP_Analyzer::UpdateConnVal(RecordVal *conn_val) - { - RecordVal *orig_endp_val = conn_val->Lookup("orig")->AsRecordVal(); - RecordVal *resp_endp_val = conn_val->Lookup("resp")->AsRecordVal(); - - orig_endp_val->Assign(0, new Val(orig->Size(), TYPE_COUNT)); - orig_endp_val->Assign(1, new Val(int(orig->state), TYPE_COUNT)); - resp_endp_val->Assign(0, new Val(resp->Size(), TYPE_COUNT)); - resp_endp_val->Assign(1, new Val(int(resp->state), TYPE_COUNT)); - - // Call children's UpdateConnVal - Analyzer::UpdateConnVal(conn_val); - - // Have to do packet_children ourselves. - LOOP_OVER_GIVEN_CHILDREN(i, packet_children) - (*i)->UpdateConnVal(conn_val); - } - -Val* TCP_Analyzer::BuildSYNPacketVal(int is_orig, const IP_Hdr* ip, - const struct tcphdr* tcp) +static RecordVal* build_syn_packet_val(int is_orig, const IP_Hdr* ip, + const struct tcphdr* tcp) { int winscale = -1; int MSS = 0; @@ -1195,8 +115,8 @@ Val* TCP_Analyzer::BuildSYNPacketVal(int is_orig, const IP_Hdr* ip, return v; } -RecordVal* TCP_Analyzer::BuildOSVal(int is_orig, const IP_Hdr* ip, - const struct tcphdr* tcp, uint32 tcp_hdr_len) +static RecordVal* build_os_val(int is_orig, const IP_Hdr* ip, + const struct tcphdr* tcp, uint32 tcp_hdr_len) { if ( ! is_orig ) // Later we might use SYN-ACK fingerprinting here. @@ -1361,6 +281,1134 @@ RecordVal* TCP_Analyzer::BuildOSVal(int is_orig, const IP_Hdr* ip, return 0; } + +static void passive_fingerprint(TCP_Analyzer* tcp, bool is_orig, + const IP_Hdr* ip, const struct tcphdr* tp, + uint32 tcp_hdr_len) + { + // is_orig will be removed once we can do SYN-ACK fingerprinting + if ( OS_version_found && is_orig ) + { + const IPAddr& orig_addr = tcp->Conn()->OrigAddr(); + AddrVal* src_addr_val = new AddrVal(orig_addr); + + if ( generate_OS_version_event->Size() == 0 || + generate_OS_version_event->Lookup(src_addr_val) ) + { + RecordVal* OS_val = build_os_val(is_orig, ip, tp, tcp_hdr_len); + + if ( OS_val ) + { // found new OS version + val_list* vl = new val_list; + vl->append(tcp->BuildConnVal()); + vl->append(src_addr_val->Ref()); + vl->append(OS_val); + tcp->ConnectionEvent(OS_version_found, vl); + } + } + + Unref(src_addr_val); + } + } + +TCP_Analyzer::TCP_Analyzer(Connection* conn) +: TransportLayerAnalyzer("TCP", conn) + { + // Set a timer to eventually time out this connection. + ADD_ANALYZER_TIMER(&TCP_Analyzer::ExpireTimer, + network_time + tcp_SYN_timeout, 0, + TIMER_TCP_EXPIRE); + + deferred_gen_event = close_deferred = 0; + + seen_first_ACK = 0; + is_active = 1; + finished = 0; + reassembling = 0; + first_packet_seen = 0; + is_partial = 0; + + orig = new TCP_Endpoint(this, 1); + resp = new TCP_Endpoint(this, 0); + + orig->SetPeer(resp); + resp->SetPeer(orig); + } + +TCP_Analyzer::~TCP_Analyzer() + { + LOOP_OVER_GIVEN_CHILDREN(i, packet_children) + delete *i; + + delete orig; + delete resp; + } + +void TCP_Analyzer::Init() + { + Analyzer::Init(); + LOOP_OVER_GIVEN_CHILDREN(i, packet_children) + (*i)->Init(); + } + +void TCP_Analyzer::Done() + { + Analyzer::Done(); + + if ( connection_pending && is_active && ! BothClosed() ) + Event(connection_pending); + + LOOP_OVER_GIVEN_CHILDREN(i, packet_children) + (*i)->Done(); + + orig->Done(); + resp->Done(); + + finished = 1; + } + +void TCP_Analyzer::EnableReassembly() + { + SetReassembler(new TCP_Reassembler(this, this, + TCP_Reassembler::Forward, orig), + new TCP_Reassembler(this, this, + TCP_Reassembler::Forward, resp)); + + reassembling = 1; + + if ( new_connection_contents ) + Event(new_connection_contents); + } + +void TCP_Analyzer::SetReassembler(TCP_Reassembler* rorig, + TCP_Reassembler* rresp) + { + orig->AddReassembler(rorig); + rorig->SetDstAnalyzer(this); + resp->AddReassembler(rresp); + rresp->SetDstAnalyzer(this); + + reassembling = 1; + + if ( new_connection_contents ) + Event(new_connection_contents); + } + +const struct tcphdr* TCP_Analyzer::ExtractTCP_Header(const u_char*& data, + int& len, int& caplen) + { + const struct tcphdr* tp = (const struct tcphdr*) data; + uint32 tcp_hdr_len = tp->th_off * 4; + + if ( tcp_hdr_len < sizeof(struct tcphdr) ) + { + Weird("bad_TCP_header_len"); + return 0; + } + + if ( tcp_hdr_len > uint32(len) || + sizeof(struct tcphdr) > uint32(caplen) ) + { + // This can happen even with the above test, due to TCP + // options. + Weird("truncated_header"); + return 0; + } + + len -= tcp_hdr_len; // remove TCP header + caplen -= tcp_hdr_len; + data += tcp_hdr_len; + + return tp; + } + +bool TCP_Analyzer::ValidateChecksum(const struct tcphdr* tp, + TCP_Endpoint* endpoint, int len, int caplen) + { + if ( ! ignore_checksums && caplen >= len && + ! endpoint->ValidChecksum(tp, len) ) + { + Weird("bad_TCP_checksum"); + endpoint->CheckHistory(HIST_CORRUPT_PKT, 'C'); + return false; + } + else + return true; + } + +void TCP_Analyzer::SetPartialStatus(TCP_Flags flags, bool is_orig) + { + if ( is_orig ) + { + if ( ! (first_packet_seen & ORIG) ) + is_partial = ! flags.SYN() || flags.ACK(); + } + else + { + if ( ! (first_packet_seen & RESP) && ! is_partial ) + is_partial = ! flags.SYN(); + } + } + +static void update_history(TCP_Flags flags, TCP_Endpoint* endpoint, + uint64 rel_seq, int len) + { + int bits_set = (flags.SYN() ? 1 : 0) + (flags.FIN() ? 1 : 0) + + (flags.RST() ? 1 : 0); + if ( bits_set > 1 ) + { + if ( flags.FIN() && flags.RST() ) + endpoint->CheckHistory(HIST_FIN_RST_PKT, 'I'); + else + endpoint->CheckHistory(HIST_MULTI_FLAG_PKT, 'Q'); + } + + else if ( bits_set == 1 ) + { + if ( flags.SYN() ) + { + char code = flags.ACK() ? 'H' : 'S'; + + if ( endpoint->CheckHistory(HIST_SYN_PKT, code) && + rel_seq != endpoint->hist_last_SYN ) + endpoint->AddHistory(code); + + endpoint->hist_last_SYN = rel_seq; + } + + if ( flags.FIN() ) + { + // For FIN's, the sequence number comes at the + // end of (any data in) the packet, not the + // beginning as for SYNs and RSTs. + if ( endpoint->CheckHistory(HIST_FIN_PKT, 'F') && + rel_seq + len != endpoint->hist_last_FIN ) + endpoint->AddHistory('F'); + + endpoint->hist_last_FIN = rel_seq + len; + } + + if ( flags.RST() ) + { + if ( endpoint->CheckHistory(HIST_RST_PKT, 'R') && + rel_seq != endpoint->hist_last_RST ) + endpoint->AddHistory('R'); + + endpoint->hist_last_RST = rel_seq; + } + } + + else + { // bits_set == 0 + if ( len ) + endpoint->CheckHistory(HIST_DATA_PKT, 'D'); + + else if ( flags.ACK() ) + endpoint->CheckHistory(HIST_ACK_PKT, 'A'); + } + } + +static void init_window(TCP_Endpoint* endpoint, TCP_Endpoint* peer, + TCP_Flags flags, bro_int_t scale, uint32 base_seq, + uint32 ack_seq) + { + // ### In the following, we could be fooled by an + // inconsistent SYN retransmission. Where's a normalizer + // when you need one? + + if ( scale < 0 ) + { // no window scaling option + if ( flags.ACK() ) + { // window scaling not negotiated + endpoint->window_scale = 0; + peer->window_scale = 0; + } + else + // We're not offering window scaling. + // Ideally, we'd remember this fact so that + // if the SYN/ACK *does* include window + // scaling, we know it won't be negotiated. + // But it's a pain to track that, and hard + // to see how an adversarial responder could + // use it to evade. Also, if we *do* want + // to track it, we could do so using + // connection_SYN_packet. + endpoint->window_scale = 0; + } + else + { + endpoint->window_scale = scale; + endpoint->window_seq = base_seq; + endpoint->window_ack_seq = ack_seq; + + peer->window_seq = ack_seq; + peer->window_ack_seq = base_seq; + } + } + +static void update_window(TCP_Endpoint* endpoint, unsigned int window, + uint32 base_seq, uint32 ack_seq, TCP_Flags flags) + { + // Note, the offered window on an initial SYN is unscaled, even + // if the SYN includes scaling, so we need to do the following + // test *before* updating the scaling information below. (Hmmm, + // how does this work for windows on SYN/ACKs? ###) + int scale = endpoint->window_scale; + window = window << scale; + + // Don't analyze window values off of SYNs, they're sometimes + // immediately rescinded. + if ( ! flags.SYN() ) + { + // ### Decide whether to accept new window based on Active + // Mapping policy. + if ( seq_delta(base_seq, endpoint->window_seq) >= 0 && + seq_delta(ack_seq, endpoint->window_ack_seq) >= 0 ) + { + uint32 new_edge = ack_seq + window; + uint32 old_edge = endpoint->window_ack_seq + endpoint->window; + int32 advance = seq_delta(new_edge, old_edge); + + if ( advance < 0 ) + { + // A window recision. We don't report these + // for FINs or RSTs, or if the connection + // has already been partially closed, since + // such recisions occur frequently in practice, + // probably as the receiver loses buffer memory + // due to its process going away. + // + // We also, for window scaling, allow a bit + // of slop ###. This is because sometimes + // there will be an apparent recision due + // to the granularity of the scaling. + if ( ! flags.FIN() && ! flags.RST() && + endpoint->state != TCP_ENDPOINT_CLOSED && + endpoint->state != TCP_ENDPOINT_RESET && + (-advance) >= (1 << scale) ) + endpoint->Conn()->Weird("window_recision"); + } + + endpoint->window = window; + endpoint->window_ack_seq = ack_seq; + endpoint->window_seq = base_seq; + } + } + } + +static void syn_weirds(TCP_Flags flags, TCP_Endpoint* endpoint, int data_len) + { + if ( flags.RST() ) + endpoint->Conn()->Weird("TCP_christmas"); + + if ( flags.URG() ) + endpoint->Conn()->Weird("baroque_SYN"); + + if ( data_len > 0 ) + // Not technically wrong according to RFC 793, but the other side + // would be forced to buffer data until the handshake succeeds, and + // that could be bad in some cases, e.g. SYN floods. + // T/TCP definitely complicates this. + endpoint->Conn()->Weird("SYN_with_data"); + } + +void TCP_Analyzer::UpdateInactiveState(double t, + TCP_Endpoint* endpoint, TCP_Endpoint* peer, + uint32 base_seq, uint32 ack_seq, + int len, int is_orig, TCP_Flags flags, + int& do_close, int& gen_event) + { + if ( flags.SYN() ) + { + if ( is_orig ) + { + if ( flags.ACK() ) + { + Weird("connection_originator_SYN_ack"); + endpoint->SetState(TCP_ENDPOINT_SYN_ACK_SENT); + } + else + endpoint->SetState(TCP_ENDPOINT_SYN_SENT); + + if ( tcp_attempt_delay ) + ADD_ANALYZER_TIMER(&TCP_Analyzer::AttemptTimer, + t + tcp_attempt_delay, 1, + TIMER_TCP_ATTEMPT); + } + else + { + if ( flags.ACK() ) + { + if ( peer->state != TCP_ENDPOINT_INACTIVE && + peer->state != TCP_ENDPOINT_PARTIAL && + ! seq_between(ack_seq, peer->StartSeq(), peer->LastSeq()) ) + Weird("bad_SYN_ack"); + } + + else if ( peer->state == TCP_ENDPOINT_SYN_ACK_SENT && + base_seq == endpoint->StartSeq() ) + { + // This is a SYN/SYN-ACK reversal, + // per the discussion in IsReuse. + // Flip the endpoints and establish + // the connection. + is_partial = 0; + Conn()->FlipRoles(); + peer->SetState(TCP_ENDPOINT_ESTABLISHED); + } + + else + Weird("simultaneous_open"); + + if ( peer->state == TCP_ENDPOINT_SYN_SENT ) + peer->SetState(TCP_ENDPOINT_ESTABLISHED); + else if ( peer->state == TCP_ENDPOINT_INACTIVE ) + { + // If we were to ignore SYNs and + // only instantiate state on SYN + // acks, then we'd do: + // peer->SetState(TCP_ENDPOINT_ESTABLISHED); + // here. + Weird("unsolicited_SYN_response"); + } + + endpoint->SetState(TCP_ENDPOINT_ESTABLISHED); + + if ( peer->state != TCP_ENDPOINT_PARTIAL ) + { + Event(connection_established); + Conn()->EnableStatusUpdateTimer(); + } + } + } + + if ( flags.FIN() ) + { + endpoint->SetState(TCP_ENDPOINT_CLOSED); + do_close = gen_event = 1; + if ( peer->state != TCP_ENDPOINT_PARTIAL && ! flags.SYN() ) + Weird("spontaneous_FIN"); + } + + if ( flags.RST() ) + { + endpoint->SetState(TCP_ENDPOINT_RESET); + + int is_reject = 0; + + if ( is_orig ) + { + // If our peer is established then we saw + // a SYN-ack but not SYN - so a reverse + // scan, and we should treat this as a + // reject. + if ( peer->state == TCP_ENDPOINT_ESTABLISHED ) + is_reject = 1; + } + + else if ( peer->state == TCP_ENDPOINT_SYN_SENT || + peer->state == TCP_ENDPOINT_SYN_ACK_SENT ) + // We're rejecting an initial SYN. + is_reject = 1; + + do_close = 1; + gen_event = ! is_reject; + + if ( is_reject ) + Event(connection_rejected); + + else if ( peer->state == TCP_ENDPOINT_INACTIVE ) + Weird("spontaneous_RST"); + } + + if ( endpoint->state == TCP_ENDPOINT_INACTIVE ) + { // No control flags to change the state. + if ( ! is_orig && len == 0 && + orig->state == TCP_ENDPOINT_SYN_SENT ) + // Some eccentric TCP's will ack an initial + // SYN prior to sending a SYN reply (hello, + // ftp.microsoft.com). For those, don't + // consider the ack as forming a partial + // connection. + ; + else + { + endpoint->SetState(TCP_ENDPOINT_PARTIAL); + Conn()->EnableStatusUpdateTimer(); + + if ( peer->state == TCP_ENDPOINT_PARTIAL ) + // We've seen both sides of a partial + // connection, report it. + Event(partial_connection); + } + } + } + +void TCP_Analyzer::UpdateSYN_SentState(TCP_Endpoint* endpoint, TCP_Endpoint* peer, + int len, int is_orig, TCP_Flags flags, + int& do_close, int& gen_event) + { + if ( flags.SYN() ) + { + if ( is_orig ) + { + if ( flags.ACK() && ! flags.FIN() && ! flags.RST() && + endpoint->state != TCP_ENDPOINT_SYN_ACK_SENT ) + Weird("repeated_SYN_with_ack"); + } + else + { + if ( ! flags.ACK() && + endpoint->state != TCP_ENDPOINT_SYN_SENT ) + Weird("repeated_SYN_reply_wo_ack"); + } + } + + if ( flags.FIN() ) + { + if ( peer->state == TCP_ENDPOINT_INACTIVE || + peer->state == TCP_ENDPOINT_SYN_SENT ) + Weird("inappropriate_FIN"); + + endpoint->SetState(TCP_ENDPOINT_CLOSED); + do_close = gen_event = 1; + } + + if ( flags.RST() ) + { + endpoint->SetState(TCP_ENDPOINT_RESET); + ConnectionReset(); + do_close = 1; + } + + else if ( len > 0 ) + Weird("data_before_established"); + } + +void TCP_Analyzer::UpdateEstablishedState( + TCP_Endpoint* endpoint, TCP_Endpoint* peer, + TCP_Flags flags, int& do_close, int& gen_event) + { + if ( flags.SYN() ) + { + if ( endpoint->state == TCP_ENDPOINT_PARTIAL && + peer->state == TCP_ENDPOINT_INACTIVE && ! flags.ACK() ) + { + Weird("SYN_after_partial"); + endpoint->SetState(TCP_ENDPOINT_SYN_SENT); + } + } + + if ( flags.FIN() && ! flags.RST() ) // ### + { // should check sequence/ack numbers here ### + endpoint->SetState(TCP_ENDPOINT_CLOSED); + + if ( peer->state == TCP_ENDPOINT_RESET && + peer->prev_state == TCP_ENDPOINT_CLOSED ) + // The peer sent a FIN followed by a RST. + // Turn it back into CLOSED state, because + // this was actually normal termination. + peer->SetState(TCP_ENDPOINT_CLOSED); + + do_close = gen_event = 1; + } + + if ( flags.RST() ) + { + endpoint->SetState(TCP_ENDPOINT_RESET); + do_close = 1; + + if ( peer->state != TCP_ENDPOINT_RESET || + peer->prev_state != TCP_ENDPOINT_ESTABLISHED ) + ConnectionReset(); + } + } + +void TCP_Analyzer::UpdateClosedState(double t, TCP_Endpoint* endpoint, + int32 delta_last, TCP_Flags flags, int& do_close) + { + if ( flags.SYN() ) + Weird("SYN_after_close"); + + if ( flags.FIN() && delta_last > 0 ) + // Probably should also complain on FIN recision. + // That requires an extra state variable to avoid + // generating slews of weird's when a TCP gets + // seriously confused (this from experience). + Weird("FIN_advanced_last_seq"); + + // Previously, our state was CLOSED, since we sent a FIN. + // If our peer was also closed, then don't change our state + // now on a RST, since this connection has already seen a FIN + // exchange. + if ( flags.RST() && endpoint->peer->state != TCP_ENDPOINT_CLOSED ) + { + endpoint->SetState(TCP_ENDPOINT_RESET); + + if ( ! endpoint->did_close ) + // RST after FIN. + do_close = 1; + + if ( connection_reset ) + ADD_ANALYZER_TIMER(&TCP_Analyzer::ResetTimer, + t + tcp_reset_delay, 1, + TIMER_TCP_RESET); + } + } + +void TCP_Analyzer::UpdateResetState(int len, TCP_Flags flags) + { + if ( flags.SYN() ) + Weird("SYN_after_reset"); + + if ( flags.FIN() ) + Weird("FIN_after_reset"); + + if ( len > 0 && ! flags.RST() ) + Weird("data_after_reset"); + } + +void TCP_Analyzer::UpdateStateMachine(double t, + TCP_Endpoint* endpoint, TCP_Endpoint* peer, + uint32 base_seq, uint32 ack_seq, + int len, int32 delta_last, int is_orig, TCP_Flags flags, + int& do_close, int& gen_event) + { + do_close = 0; // whether to report the connection as closed + gen_event = 0; // if so, whether to generate an event + + switch ( endpoint->state ) { + + case TCP_ENDPOINT_INACTIVE: + UpdateInactiveState(t, endpoint, peer, base_seq, ack_seq, + len, is_orig, flags, + do_close, gen_event); + break; + + case TCP_ENDPOINT_SYN_SENT: + case TCP_ENDPOINT_SYN_ACK_SENT: + UpdateSYN_SentState(endpoint, peer, len, is_orig, flags, do_close, + gen_event); + break; + + case TCP_ENDPOINT_ESTABLISHED: + case TCP_ENDPOINT_PARTIAL: + UpdateEstablishedState(endpoint, peer, flags, do_close, gen_event); + break; + + case TCP_ENDPOINT_CLOSED: + UpdateClosedState(t, endpoint, delta_last, flags, do_close); + break; + + case TCP_ENDPOINT_RESET: + UpdateResetState(len, flags); + break; + } + } + +void TCP_Analyzer::GeneratePacketEvent( + uint64 rel_seq, uint64 rel_ack, + const u_char* data, int len, int caplen, + int is_orig, TCP_Flags flags) + { + char tcp_flags[256]; + int tcp_flag_len = 0; + + if ( flags.SYN() ) tcp_flags[tcp_flag_len++] = 'S'; + if ( flags.FIN() ) tcp_flags[tcp_flag_len++] = 'F'; + if ( flags.RST() ) tcp_flags[tcp_flag_len++] = 'R'; + if ( flags.ACK() ) tcp_flags[tcp_flag_len++] = 'A'; + if ( flags.PUSH() ) tcp_flags[tcp_flag_len++] = 'P'; + if ( flags.URG() ) tcp_flags[tcp_flag_len++] = 'U'; + + tcp_flags[tcp_flag_len] = '\0'; + + val_list* vl = new val_list(); + + vl->append(BuildConnVal()); + vl->append(new Val(is_orig, TYPE_BOOL)); + vl->append(new StringVal(tcp_flags)); + vl->append(new Val(rel_seq, TYPE_COUNT)); + vl->append(new Val(flags.ACK() ? rel_ack : 0, TYPE_COUNT)); + vl->append(new Val(len, TYPE_COUNT)); + + // We need the min() here because Ethernet padding can lead to + // caplen > len. + vl->append(new StringVal(min(caplen, len), (const char*) data)); + + ConnectionEvent(tcp_packet, vl); + } + +int TCP_Analyzer::DeliverData(double t, const u_char* data, int len, int caplen, + const IP_Hdr* ip, const struct tcphdr* tp, + TCP_Endpoint* endpoint, uint64 rel_data_seq, + int is_orig, TCP_Flags flags) + { + return endpoint->DataSent(t, rel_data_seq, len, caplen, data, ip, tp); + } + +void TCP_Analyzer::CheckRecording(int need_contents, TCP_Flags flags) + { + bool record_current_content = need_contents || Conn()->RecordContents(); + bool record_current_packet = + Conn()->RecordPackets() || + flags.SYN() || flags.FIN() || flags.RST(); + + Conn()->SetRecordCurrentContent(record_current_content); + Conn()->SetRecordCurrentPacket(record_current_packet); + } + +void TCP_Analyzer::CheckPIA_FirstPacket(int is_orig, const IP_Hdr* ip) + { + if ( is_orig && ! (first_packet_seen & ORIG) ) + { + pia::PIA_TCP* pia = static_cast(Conn()->GetPrimaryPIA()); + if ( pia ) + pia->FirstPacket(is_orig, ip); + first_packet_seen |= ORIG; + } + + if ( ! is_orig && ! (first_packet_seen & RESP) ) + { + pia::PIA_TCP* pia = static_cast(Conn()->GetPrimaryPIA()); + if ( pia ) + pia->FirstPacket(is_orig, ip); + first_packet_seen |= RESP; + } + } + +static uint64 get_relative_seq(const TCP_Endpoint* endpoint, + uint32 cur_base, uint32 last, uint32 wraps, + bool* underflow = 0) + { + int32 delta = seq_delta(cur_base, last); + + if ( delta < 0 ) + { + if ( wraps && cur_base > last ) + // Seems to be a part of a previous 32-bit sequence space. + --wraps; + } + + else if ( delta > 0 ) + { + if ( cur_base < last ) + // The sequence space wrapped around. + ++wraps; + } + + if ( wraps == 0 ) + { + delta = seq_delta(cur_base, endpoint->StartSeq()); + + if ( underflow && delta < 0 ) + *underflow = true; + + return delta; + } + + return endpoint->ToRelativeSeqSpace(cur_base, wraps); + } + +static int get_segment_len(int payload_len, TCP_Flags flags) + { + int seg_len = payload_len; + + if ( flags.SYN() ) + // SYN consumes a byte of sequence space. + ++seg_len; + + if ( flags.FIN() ) + // FIN consumes a bytes of sequence space. + ++seg_len; + + if ( flags.RST() ) + // Don't include the data in the computation of + // the sequence space for this connection, as + // it's not in fact part of the TCP stream. + seg_len -= payload_len; + + return seg_len; + } + +static void init_endpoint(TCP_Endpoint* endpoint, TCP_Flags flags, + uint32 first_seg_seq, uint32 last_seq, double t) + { + switch ( endpoint->state ) { + case TCP_ENDPOINT_INACTIVE: + if ( flags.SYN() ) + { + endpoint->InitAckSeq(first_seg_seq); + endpoint->InitStartSeq(first_seg_seq); + } + else + { + // This is a partial connection - set up the initial sequence + // numbers as though we saw a SYN, to keep the relative byte + // numbering consistent. + endpoint->InitAckSeq(first_seg_seq - 1); + endpoint->InitStartSeq(first_seg_seq - 1); + } + + endpoint->InitLastSeq(last_seq); + endpoint->start_time = t; + break; + + case TCP_ENDPOINT_SYN_SENT: + case TCP_ENDPOINT_SYN_ACK_SENT: + if ( flags.SYN() && first_seg_seq != endpoint->StartSeq() ) + { + endpoint->Conn()->Weird("SYN_seq_jump"); + endpoint->InitStartSeq(first_seg_seq); + endpoint->InitAckSeq(first_seg_seq); + endpoint->InitLastSeq(last_seq); + } + break; + + case TCP_ENDPOINT_ESTABLISHED: + case TCP_ENDPOINT_PARTIAL: + if ( flags.SYN() ) + { + if ( endpoint->Size() > 0 ) + endpoint->Conn()->Weird("SYN_inside_connection"); + + if ( first_seg_seq != endpoint->StartSeq() ) + endpoint->Conn()->Weird("SYN_seq_jump"); + + // Make a guess that somehow the connection didn't get established, + // and this SYN will be the one that actually sets it up. + endpoint->InitStartSeq(first_seg_seq); + endpoint->InitAckSeq(first_seg_seq); + endpoint->InitLastSeq(last_seq); + } + break; + + case TCP_ENDPOINT_RESET: + if ( flags.SYN() ) + { + if ( endpoint->prev_state == TCP_ENDPOINT_INACTIVE ) + { + // Seq. numbers were initialized by a RST packet from this + // endpoint, but now that a SYN is seen from it, that could mean + // the earlier RST was spoofed/injected, so re-initialize. This + // mostly just helps prevent misrepresentations of payload sizes + // that are based on bad initial sequence values. + endpoint->InitStartSeq(first_seg_seq); + endpoint->InitAckSeq(first_seg_seq); + endpoint->InitLastSeq(last_seq); + } + } + break; + + default: + break; + } + } + +static void init_peer(TCP_Endpoint* peer, TCP_Endpoint* endpoint, + TCP_Flags flags, uint32 ack_seq) + { + if ( ! flags.SYN() && ! flags.FIN() && ! flags.RST() ) + { + if ( endpoint->state == TCP_ENDPOINT_SYN_SENT || + endpoint->state == TCP_ENDPOINT_SYN_ACK_SENT || + endpoint->state == TCP_ENDPOINT_ESTABLISHED ) + { + // We've already sent a SYN, but that + // hasn't roused the other end, yet we're + // ack'ing their data. + + if ( ! endpoint->Conn()->DidWeird() ) + endpoint->Conn()->Weird("possible_split_routing"); + } + } + + // Start the sequence numbering as if there was an initial + // SYN, so the relative numbering of subsequent data packets + // stays consistent. + peer->InitStartSeq(ack_seq - 1); + peer->InitAckSeq(ack_seq - 1); + peer->InitLastSeq(ack_seq - 1); + } + +static void update_ack_seq(TCP_Endpoint* endpoint, uint32 ack_seq) + { + int32 delta_ack = seq_delta(ack_seq, endpoint->AckSeq()); + + if ( ack_seq == 0 && delta_ack > TOO_LARGE_SEQ_DELTA ) + // More likely that this is a broken ack than a + // large connection that happens to land on 0 in the + // sequence space. + ; + else if ( delta_ack > 0 ) + endpoint->UpdateAckSeq(ack_seq); + } + +// Returns the difference between last_seq and the last sequence +// seen by the endpoint (may be negative). +static int32 update_last_seq(TCP_Endpoint* endpoint, uint32 last_seq, + TCP_Flags flags) + { + int32 delta_last = seq_delta(last_seq, endpoint->LastSeq()); + + if ( (flags.SYN() || flags.RST()) && + (delta_last > TOO_LARGE_SEQ_DELTA || + delta_last < -TOO_LARGE_SEQ_DELTA) ) + // ### perhaps trust RST seq #'s if initial and not too + // outlandish, but not if they're coming after the other + // side has sent a FIN - trust the FIN ack instead + ; + + else if ( flags.FIN() && + endpoint->LastSeq() == endpoint->StartSeq() + 1 ) + // Update last_seq based on the FIN even if delta_last < 0. + // This is to accommodate > 2 GB connections for which + // we've only seen the SYN and the FIN (hence the check + // for last_seq == start_seq + 1). + endpoint->UpdateLastSeq(last_seq); + + else if ( endpoint->state == TCP_ENDPOINT_RESET ) + // don't trust any subsequent sequence numbers + ; + + else if ( delta_last > 0 ) + // ### check for large jumps here. + // ## endpoint->last_seq = last_seq; + endpoint->UpdateLastSeq(last_seq); + + else if ( delta_last <= 0 ) + { // ### ++retransmit, unless this is a pure ack + } + + return delta_last; + } + +void TCP_Analyzer::DeliverPacket(int len, const u_char* data, bool is_orig, + uint64 seq, const IP_Hdr* ip, int caplen) + { + TransportLayerAnalyzer::DeliverPacket(len, data, orig, seq, ip, caplen); + + const struct tcphdr* tp = ExtractTCP_Header(data, len, caplen); + if ( ! tp ) + return; + + // We need the min() here because Ethernet frame padding can lead to + // caplen > len. + if ( packet_contents ) + PacketContents(data, min(len, caplen)); + + TCP_Endpoint* endpoint = is_orig ? orig : resp; + TCP_Endpoint* peer = endpoint->peer; + + if ( ! ValidateChecksum(tp, endpoint, len, caplen) ) + return; + + uint32 tcp_hdr_len = data - (const u_char*) tp; + TCP_Flags flags(tp); + SetPartialStatus(flags, endpoint->IsOrig()); + + uint32 base_seq = ntohl(tp->th_seq); + uint32 ack_seq = ntohl(tp->th_ack); + + int seg_len = get_segment_len(len, flags); + uint32 seq_one_past_segment = base_seq + seg_len; + + init_endpoint(endpoint, flags, base_seq, seq_one_past_segment, + current_timestamp); + + bool seq_underflow = false; + uint64 rel_seq = get_relative_seq(endpoint, base_seq, endpoint->LastSeq(), + endpoint->SeqWraps(), &seq_underflow); + + if ( seq_underflow && ! flags.RST() ) + // Can't tell if if this is a retransmit/out-of-order or something + // before the sequence Bro initialized the endpoint at or the TCP is + // just broken and sending garbage sequences. In either case, some + // standard analysis doesn't apply (e.g. reassembly). + Weird("TCP_seq_underflow_or_misorder"); + + update_history(flags, endpoint, rel_seq, len); + update_window(endpoint, ntohs(tp->th_win), base_seq, ack_seq, flags); + + if ( ! orig->did_close || ! resp->did_close ) + Conn()->SetLastTime(current_timestamp); + + if ( flags.SYN() ) + { + syn_weirds(flags, endpoint, len); + RecordVal* SYN_vals = build_syn_packet_val(is_orig, ip, tp); + init_window(endpoint, peer, flags, SYN_vals->Lookup(5)->CoerceToInt(), + base_seq, ack_seq); + + if ( connection_SYN_packet ) + { + val_list* vl = new val_list; + vl->append(BuildConnVal()); + vl->append(SYN_vals->Ref()); + ConnectionEvent(connection_SYN_packet, vl); + } + + passive_fingerprint(this, is_orig, ip, tp, tcp_hdr_len); + + Unref(SYN_vals); + } + + if ( flags.FIN() ) + { + ++endpoint->FIN_cnt; + + if ( endpoint->FIN_cnt >= tcp_storm_thresh && current_timestamp < + endpoint->last_time + tcp_storm_interarrival_thresh ) + Weird("FIN_storm"); + + endpoint->FIN_seq = rel_seq + seg_len; + } + + if ( flags.RST() ) + { + ++endpoint->RST_cnt; + + if ( endpoint->RST_cnt >= tcp_storm_thresh && current_timestamp < + endpoint->last_time + tcp_storm_interarrival_thresh ) + Weird("RST_storm"); + + // This now happens often enough that it's + // not in the least interesting. + //if ( len > 0 ) + // Weird("RST_with_data"); + + PacketWithRST(); + } + + uint64 rel_ack = 0; + + if ( flags.ACK() ) + { + if ( is_orig && ! seen_first_ACK && + (endpoint->state == TCP_ENDPOINT_ESTABLISHED || + endpoint->state == TCP_ENDPOINT_SYN_SENT) ) + { + seen_first_ACK = 1; + Event(connection_first_ACK); + } + + if ( peer->state == TCP_ENDPOINT_INACTIVE ) + { + rel_ack = 1; + init_peer(peer, endpoint, flags, ack_seq); + } + else + { + bool ack_underflow = false; + rel_ack = get_relative_seq(peer, ack_seq, peer->AckSeq(), + peer->AckWraps(), &ack_underflow); + + if ( ack_underflow ) + { + rel_ack = 0; + Weird("TCP_ack_underflow_or_misorder"); + } + else if ( ! flags.RST() ) + // Don't trust ack's in RSt packets. + update_ack_seq(peer, ack_seq); + } + + peer->AckReceived(rel_ack); + } + + int32 delta_last = update_last_seq(endpoint, seq_one_past_segment, flags); + endpoint->last_time = current_timestamp; + + int do_close; + int gen_event; + UpdateStateMachine(current_timestamp, endpoint, peer, base_seq, ack_seq, + len, delta_last, is_orig, flags, do_close, gen_event); + + if ( tcp_packet ) + GeneratePacketEvent(rel_seq, rel_ack, data, len, caplen, is_orig, + flags); + + if ( tcp_option && tcp_hdr_len > sizeof(*tp) && + tcp_hdr_len <= uint32(caplen) ) + ParseTCPOptions(tp, TCPOptionEvent, this, is_orig, 0); + + if ( DEBUG_tcp_data_sent ) + { + DEBUG_MSG("%.6f before DataSent: len=%d caplen=%d skip=%d\n", + network_time, len, caplen, Skipping()); + } + + uint64 rel_data_seq = flags.SYN() ? rel_seq + 1 : rel_seq; + + int need_contents = 0; + if ( len > 0 && (caplen >= len || packet_children.size()) && + ! flags.RST() && ! Skipping() && ! seq_underflow ) + need_contents = DeliverData(current_timestamp, data, len, caplen, ip, + tp, endpoint, rel_data_seq, is_orig, flags); + + endpoint->CheckEOF(); + + if ( do_close ) + { + // We need to postpone doing this until after we process + // DataSent, so we don't generate a connection_finished event + // until after data perhaps included with the FIN is processed. + ConnectionClosed(endpoint, peer, gen_event); + } + + CheckRecording(need_contents, flags); + + // Handle child_packet analyzers. Note: This happens *after* the + // packet has been processed and the TCP state updated. + LOOP_OVER_GIVEN_CHILDREN(i, packet_children) + (*i)->NextPacket(len, data, is_orig, rel_data_seq, ip, caplen); + + if ( ! reassembling ) + ForwardPacket(len, data, is_orig, rel_data_seq, ip, caplen); + + CheckPIA_FirstPacket(is_orig, ip); + } + +void TCP_Analyzer::DeliverStream(int len, const u_char* data, bool orig) + { + Analyzer::DeliverStream(len, data, orig); + } + +void TCP_Analyzer::Undelivered(uint64 seq, int len, bool is_orig) + { + Analyzer::Undelivered(seq, len, orig); + } + +void TCP_Analyzer::FlipRoles() + { + Analyzer::FlipRoles(); + + sessions->tcp_stats.FlipState(orig->state, resp->state); + TCP_Endpoint* tmp_ep = resp; + resp = orig; + orig = tmp_ep; + orig->is_orig = !orig->is_orig; + resp->is_orig = !resp->is_orig; + } + +void TCP_Analyzer::UpdateConnVal(RecordVal *conn_val) + { + RecordVal *orig_endp_val = conn_val->Lookup("orig")->AsRecordVal(); + RecordVal *resp_endp_val = conn_val->Lookup("resp")->AsRecordVal(); + + orig_endp_val->Assign(0, new Val(orig->Size(), TYPE_COUNT)); + orig_endp_val->Assign(1, new Val(int(orig->state), TYPE_COUNT)); + resp_endp_val->Assign(0, new Val(resp->Size(), TYPE_COUNT)); + resp_endp_val->Assign(1, new Val(int(resp->state), TYPE_COUNT)); + + // Call children's UpdateConnVal + Analyzer::UpdateConnVal(conn_val); + + // Have to do packet_children ourselves. + LOOP_OVER_GIVEN_CHILDREN(i, packet_children) + (*i)->UpdateConnVal(conn_val); + } + int TCP_Analyzer::ParseTCPOptions(const struct tcphdr* tcp, proc_tcp_option_t proc, TCP_Analyzer* analyzer, @@ -1849,11 +1897,11 @@ void TCP_ApplicationAnalyzer::ProtocolViolation(const char* reason, } void TCP_ApplicationAnalyzer::DeliverPacket(int len, const u_char* data, - bool is_orig, int seq, + bool is_orig, uint64 seq, const IP_Hdr* ip, int caplen) { Analyzer::DeliverPacket(len, data, is_orig, seq, ip, caplen); - DBG_LOG(DBG_ANALYZER, "TCP_ApplicationAnalyzer ignoring DeliverPacket(%d, %s, %d, %p, %d) [%s%s]", + DBG_LOG(DBG_ANALYZER, "TCP_ApplicationAnalyzer ignoring DeliverPacket(%d, %s, %"PRIu64", %p, %d) [%s%s]", len, is_orig ? "T" : "F", seq, ip, caplen, fmt_bytes((const char*) data, min(40, len)), len > 40 ? "..." : ""); } @@ -1930,7 +1978,7 @@ int endian_flip(int n) return ((n & 0xff) << 8) | ((n & 0xff00) >> 8); } -int TCPStats_Endpoint::DataSent(double /* t */, int seq, int len, int caplen, +int TCPStats_Endpoint::DataSent(double /* t */, uint64 seq, int len, int caplen, const u_char* /* data */, const IP_Hdr* ip, const struct tcphdr* /* tp */) { @@ -1990,14 +2038,14 @@ int TCPStats_Endpoint::DataSent(double /* t */, int seq, int len, int caplen, ++num_in_order; - int top_seq = seq + len; + uint64 top_seq = seq + len; - int data_in_flight = endp->LastSeq() - endp->AckSeq(); + int32 data_in_flight = seq_delta(endp->LastSeq(), endp->AckSeq()); if ( data_in_flight < 0 ) data_in_flight = 0; - int seq_delta = top_seq - max_top_seq; - if ( seq_delta <= 0 ) + int64 sequence_delta = top_seq - max_top_seq; + if ( sequence_delta <= 0 ) { if ( ! BifConst::ignore_keep_alive_rexmit || len > 1 || data_in_flight > 0 ) { @@ -2005,7 +2053,7 @@ int TCPStats_Endpoint::DataSent(double /* t */, int seq, int len, int caplen, num_rxmit_bytes += len; } - DEBUG_MSG("%.6f rexmit %d + %d <= %d data_in_flight = %d\n", + DEBUG_MSG("%.6f rexmit %"PRIu64" + %d <= %"PRIu64" data_in_flight = %d\n", network_time, seq, len, max_top_seq, data_in_flight); if ( tcp_rexmit ) @@ -2073,7 +2121,7 @@ void TCPStats_Analyzer::Done() ConnectionEvent(conn_stats, vl); } -void TCPStats_Analyzer::DeliverPacket(int len, const u_char* data, bool is_orig, int seq, const IP_Hdr* ip, int caplen) +void TCPStats_Analyzer::DeliverPacket(int len, const u_char* data, bool is_orig, uint64 seq, const IP_Hdr* ip, int caplen) { TCP_ApplicationAnalyzer::DeliverPacket(len, data, is_orig, seq, ip, caplen); diff --git a/src/analyzer/protocol/tcp/TCP.h b/src/analyzer/protocol/tcp/TCP.h index b2649b4ab8..ab3836d2ea 100644 --- a/src/analyzer/protocol/tcp/TCP.h +++ b/src/analyzer/protocol/tcp/TCP.h @@ -102,9 +102,9 @@ protected: // Analyzer interface. virtual void Init(); virtual void Done(); - virtual void DeliverPacket(int len, const u_char* data, bool orig, int seq, const IP_Hdr* ip, int caplen); + virtual void DeliverPacket(int len, const u_char* data, bool orig, uint64 seq, const IP_Hdr* ip, int caplen); virtual void DeliverStream(int len, const u_char* data, bool orig); - virtual void Undelivered(int seq, int len, bool orig); + virtual void Undelivered(uint64 seq, int len, bool orig); virtual void FlipRoles(); virtual bool IsReuse(double t, const u_char* pkt); @@ -119,42 +119,7 @@ protected: bool ValidateChecksum(const struct tcphdr* tp, TCP_Endpoint* endpoint, int len, int caplen); - // Update analysis based on flag combinations. The endpoint, base_seq - // and len are needed for tracking various history information. - // dst_port is needed for trimming of FIN packets. - void CheckFlagCombos(TCP_Flags flags, TCP_Endpoint* endpoint, - uint32 base_seq, int len, int dst_port); - - void UpdateWindow(TCP_Endpoint* endpoint, unsigned int window, - uint32 base_seq, uint32 ack_seq, - TCP_Flags flags); - - void ProcessSYN(const IP_Hdr* ip, const struct tcphdr* tp, - uint32 tcp_hdr_len, int& seq_len, - TCP_Endpoint* endpoint, TCP_Endpoint* peer, - uint32 base_seq, uint32 ack_seq, - const IPAddr& orig_addr, - int is_orig, TCP_Flags flags); - - void ProcessFIN(double t, TCP_Endpoint* endpoint, int& seq_len, - uint32 base_seq); - - void ProcessRST(double t, TCP_Endpoint* endpoint, const IP_Hdr* ip, - uint32 base_seq, int len, int& seq_len); - - void ProcessACK(TCP_Endpoint* endpoint, TCP_Endpoint* peer, - uint32 ack_seq, int is_orig, TCP_Flags flags); - - void ProcessFlags(double t, const IP_Hdr* ip, const struct tcphdr* tp, - uint32 tcp_hdr_len, int len, int& seq_len, - TCP_Endpoint* endpoint, TCP_Endpoint* peer, - uint32 base_seq, uint32 ack_seq, - const IPAddr& orig_addr, - int is_orig, TCP_Flags flags); - - void TransitionFromInactive(double t, TCP_Endpoint* endpoint, - uint32 base_seq, uint32 last_seq, - int SYN); + void SetPartialStatus(TCP_Flags flags, bool is_orig); // Update the state machine of the TCPs based on the activity. This // includes our pseudo-states such as TCP_ENDPOINT_PARTIAL. @@ -164,8 +129,8 @@ protected: // this fact. void UpdateStateMachine(double t, TCP_Endpoint* endpoint, TCP_Endpoint* peer, - uint32 base_seq, uint32 ack_seq, uint32 last_seq, - int len, int delta_last, int is_orig, TCP_Flags flags, + uint32 base_seq, uint32 ack_seq, + int len, int32 delta_last, int is_orig, TCP_Flags flags, int& do_close, int& gen_event); void UpdateInactiveState(double t, @@ -174,43 +139,31 @@ protected: int len, int is_orig, TCP_Flags flags, int& do_close, int& gen_event); - void UpdateSYN_SentState(double t, - TCP_Endpoint* endpoint, TCP_Endpoint* peer, - uint32 base_seq, uint32 last_seq, - int len, int is_orig, TCP_Flags flags, - int& do_close, int& gen_event); + void UpdateSYN_SentState(TCP_Endpoint* endpoint, TCP_Endpoint* peer, + int len, int is_orig, TCP_Flags flags, + int& do_close, int& gen_event); - void UpdateEstablishedState(double t, - TCP_Endpoint* endpoint, TCP_Endpoint* peer, - uint32 base_seq, uint32 last_seq, - int is_orig, TCP_Flags flags, - int& do_close, int& gen_event); + void UpdateEstablishedState(TCP_Endpoint* endpoint, TCP_Endpoint* peer, + TCP_Flags flags, int& do_close, int& gen_event); void UpdateClosedState(double t, TCP_Endpoint* endpoint, - int delta_last, TCP_Flags flags, + int32 delta_last, TCP_Flags flags, int& do_close); - void UpdateResetState(int len, TCP_Flags flags, TCP_Endpoint* endpoint, - uint32 base_seq, uint32 last_seq); + void UpdateResetState(int len, TCP_Flags flags); - void GeneratePacketEvent(TCP_Endpoint* endpoint, TCP_Endpoint* peer, - uint32 base_seq, uint32 ack_seq, - const u_char* data, int len, int caplen, - int is_orig, TCP_Flags flags); + void GeneratePacketEvent(uint64 rel_seq, uint64 rel_ack, + const u_char* data, int len, int caplen, + int is_orig, TCP_Flags flags); int DeliverData(double t, const u_char* data, int len, int caplen, const IP_Hdr* ip, const struct tcphdr* tp, - TCP_Endpoint* endpoint, uint32 base_seq, + TCP_Endpoint* endpoint, uint64 rel_data_seq, int is_orig, TCP_Flags flags); void CheckRecording(int need_contents, TCP_Flags flags); void CheckPIA_FirstPacket(int is_orig, const IP_Hdr* ip); - // Returns the difference between last_seq and the last sequence - // seen by the endpoint (may be negative). - int UpdateLastSeq(TCP_Endpoint* endpoint, uint32 last_seq, - TCP_Flags flags); - friend class ConnectionTimer; void AttemptTimer(double t); void PartialCloseTimer(double t); @@ -228,12 +181,6 @@ protected: void SetReassembler(tcp::TCP_Reassembler* rorig, tcp::TCP_Reassembler* rresp); - Val* BuildSYNPacketVal(int is_orig, - const IP_Hdr* ip, const struct tcphdr* tcp); - - RecordVal* BuildOSVal(int is_orig, const IP_Hdr* ip, - const struct tcphdr* tcp, uint32 tcp_hdr_len); - // Needs to be static because it's passed as a pointer-to-function // rather than pointer-to-member-function. static int TCPOptionEvent(unsigned int opt, unsigned int optlen, @@ -304,7 +251,7 @@ public: virtual void PacketWithRST(); virtual void DeliverPacket(int len, const u_char* data, bool orig, - int seq, const IP_Hdr* ip, int caplen); + uint64 seq, const IP_Hdr* ip, int caplen); virtual void Init(); // This suppresses violations if the TCP connection wasn't @@ -341,7 +288,7 @@ class TCPStats_Endpoint { public: TCPStats_Endpoint(TCP_Endpoint* endp); - int DataSent(double t, int seq, int len, int caplen, const u_char* data, + int DataSent(double t, uint64 seq, int len, int caplen, const u_char* data, const IP_Hdr* ip, const struct tcphdr* tp); RecordVal* BuildStats(); @@ -354,7 +301,7 @@ protected: int num_in_order; int num_OO; int num_repl; - int max_top_seq; + uint64 max_top_seq; int last_id; int endian_type; }; @@ -372,7 +319,7 @@ public: protected: virtual void DeliverPacket(int len, const u_char* data, bool is_orig, - int seq, const IP_Hdr* ip, int caplen); + uint64 seq, const IP_Hdr* ip, int caplen); TCPStats_Endpoint* orig_stats; TCPStats_Endpoint* resp_stats; diff --git a/src/analyzer/protocol/tcp/TCP_Endpoint.cc b/src/analyzer/protocol/tcp/TCP_Endpoint.cc index ad642a46e3..2e8d6e593b 100644 --- a/src/analyzer/protocol/tcp/TCP_Endpoint.cc +++ b/src/analyzer/protocol/tcp/TCP_Endpoint.cc @@ -20,7 +20,7 @@ TCP_Endpoint::TCP_Endpoint(TCP_Analyzer* arg_analyzer, int arg_is_orig) peer = 0; start_time = last_time = 0.0; start_seq = last_seq = ack_seq = 0; - last_seq_high = ack_seq_high = 0; + seq_wraps = ack_wraps = 0; window = 0; window_scale = 0; window_seq = window_ack_seq = 0; @@ -108,7 +108,8 @@ void TCP_Endpoint::CheckEOF() contents_processor->CheckEOF(); } -void TCP_Endpoint::SizeBufferedData(int& waiting_on_hole, int& waiting_on_ack) +void TCP_Endpoint::SizeBufferedData(uint64& waiting_on_hole, + uint64& waiting_on_ack) { if ( contents_processor ) contents_processor->SizeBufferedData(waiting_on_hole, waiting_on_ack); @@ -159,7 +160,7 @@ void TCP_Endpoint::SetState(EndpointState new_state) } } -bro_int_t TCP_Endpoint::Size() const +uint64 TCP_Endpoint::Size() const { if ( prev_state == TCP_ENDPOINT_SYN_SENT && state == TCP_ENDPOINT_RESET && peer->state == TCP_ENDPOINT_INACTIVE && ! NoDataAcked() ) @@ -168,14 +169,18 @@ bro_int_t TCP_Endpoint::Size() const // and there was never a chance for this endpoint to send data anyway. return 0; - bro_int_t size; + uint64 size; + uint64 last_seq_64 = ToFullSeqSpace(LastSeq(), SeqWraps()); + uint64 ack_seq_64 = ToFullSeqSpace(AckSeq(), AckWraps()); - uint64 last_seq_64 = (uint64(last_seq_high) << 32) | last_seq; - uint64 ack_seq_64 = (uint64(ack_seq_high) << 32) | ack_seq; + // Going straight to relative sequence numbers and comparing those might + // make more sense, but there's some cases (e.g. due to RSTs) where + // last_seq might not be initialized to a trustworthy value such that + // rel_seq > rel_ack, but last_seq_64 < start_seq, which is obviously wrong. if ( last_seq_64 > ack_seq_64 ) - size = last_seq_64 - start_seq; + size = last_seq_64 - StartSeqI64(); else - size = ack_seq_64 - start_seq; + size = ack_seq_64 - StartSeqI64(); // Don't include SYN octet in sequence space. For partial connections // (no SYN seen), we're still careful to adjust start_seq as though @@ -190,7 +195,7 @@ bro_int_t TCP_Endpoint::Size() const return size; } -int TCP_Endpoint::DataSent(double t, int seq, int len, int caplen, +int TCP_Endpoint::DataSent(double t, uint64 seq, int len, int caplen, const u_char* data, const IP_Hdr* ip, const struct tcphdr* tp) { @@ -205,7 +210,7 @@ int TCP_Endpoint::DataSent(double t, int seq, int len, int caplen, if ( contents_file && ! contents_processor && seq + len > contents_start_seq ) { - int under_seq = contents_start_seq - seq; + int64 under_seq = contents_start_seq - seq; if ( under_seq > 0 ) { seq += under_seq; @@ -236,7 +241,7 @@ int TCP_Endpoint::DataSent(double t, int seq, int len, int caplen, return status; } -void TCP_Endpoint::AckReceived(int seq) +void TCP_Endpoint::AckReceived(uint64 seq) { if ( contents_processor ) contents_processor->AckReceived(seq); @@ -246,7 +251,7 @@ void TCP_Endpoint::SetContentsFile(BroFile* f) { Ref(f); contents_file = f; - contents_start_seq = last_seq - start_seq; + contents_start_seq = ToRelativeSeqSpace(last_seq, seq_wraps); if ( contents_start_seq == 0 ) contents_start_seq = 1; // skip SYN diff --git a/src/analyzer/protocol/tcp/TCP_Endpoint.h b/src/analyzer/protocol/tcp/TCP_Endpoint.h index 31e239225b..95186c583a 100644 --- a/src/analyzer/protocol/tcp/TCP_Endpoint.h +++ b/src/analyzer/protocol/tcp/TCP_Endpoint.h @@ -38,32 +38,94 @@ public: EndpointState State() const { return state; } void SetState(EndpointState new_state); - bro_int_t Size() const; + uint64 Size() const; int IsActive() const { return state != TCP_ENDPOINT_INACTIVE && ! did_close; } double StartTime() const { return start_time; } double LastTime() const { return last_time; } - uint32 StartSeq() const { return start_seq; } + /** + * @return The starting TCP sequence number for this endpoint. + */ + uint32 StartSeq() const { return static_cast(start_seq); } + + /** + * @return The starting TCP sequence number for this endpoint, in terms + * of a signed sequence space, which may account for initial + * sequence space wraparounds (underflow/overflow). + */ + int64 StartSeqI64() const { return start_seq; } + + /** + * @return The sequence number after the last TCP sequence number seen + * from this endpoint. + */ uint32 LastSeq() const { return last_seq; } + + /** + * @return The last TCP acknowledgement number seen from this endpoint. + */ uint32 AckSeq() const { return ack_seq; } - void InitStartSeq(uint32 seq) { start_seq = seq; } + /** + * @return The number of times the TCP sequence has wrapped around + * for this endpoint (i.e. overflowed a uint32). + */ + uint32 SeqWraps() const { return seq_wraps; } + + /** + * @return The number of times the TCP acknowledgement sequence has + * wrapped around for this endpoint (i.e. overflowed a uint32). + */ + uint32 AckWraps() const { return ack_wraps; } + + /** + * @param wraps Number of times a 32-bit sequence space has wrapped. + * @return A 64-bit sequence space number it would take to overflow + * a 32-bit sequence space \a wraps number of times. + */ + static uint64 ToFullSeqSpace(uint32 wraps) + { return (uint64(wraps) << 32); } + + /** + * @param tcp_seq_num A 32-bit TCP sequence space number. + * @param wraparounds Number of times a 32-bit sequence space has wrapped. + * @return \a tcp_seq_num expanded out in to a 64-bit sequence space, + * accounting for the number of times the 32-bit space overflowed. + */ + static uint64 ToFullSeqSpace(uint32 tcp_seq_num, uint32 wraparounds) + { return ToFullSeqSpace(wraparounds) + tcp_seq_num; } + + /** + * @param tcp_seq_num A 32-bit TCP sequence space number. + * @param wraparounds Number of times a 32-bit sequence space has wrapped. + * @return \a tcp_seq_num expanded out in to a 64-bit sequence space, + * accounting for the number of times the 32-bit space overflowed + * and relative to the starting sequence number for this endpoint. + */ + uint64 ToRelativeSeqSpace(uint32 tcp_seq_num, uint32 wraparounds) const + { + return ToFullSeqSpace(tcp_seq_num, wraparounds) - StartSeqI64(); + } + + void InitStartSeq(int64 seq) { start_seq = seq; } void InitLastSeq(uint32 seq) { last_seq = seq; } void InitAckSeq(uint32 seq) { ack_seq = seq; } void UpdateLastSeq(uint32 seq) { if ( seq < last_seq ) - ++last_seq_high; + ++seq_wraps; + last_seq = seq; } void UpdateAckSeq(uint32 seq) { if ( seq < ack_seq ) - ++ack_seq_high; + ++ack_wraps; + ack_seq = seq; } @@ -71,7 +133,10 @@ public: // We allow for possibly one octet being ack'd in the case of // an initial SYN exchange. int NoDataAcked() const - { return ack_seq == start_seq || ack_seq == start_seq + 1; } + { + uint64 ack = ToFullSeqSpace(ack_seq, ack_wraps); + return ack == StartSeqI64() || ack == StartSeqI64() + 1; + } Connection* Conn() const; @@ -96,16 +161,16 @@ public: // // If we're not processing contents, then naturally each of // these is empty. - void SizeBufferedData(int& waiting_on_hole, int& waiting_on_ack); + void SizeBufferedData(uint64& waiting_on_hole, uint64& waiting_on_ack); int ValidChecksum(const struct tcphdr* tp, int len) const; // Returns true if the data was used (and hence should be recorded // in the save file), false otherwise. - int DataSent(double t, int seq, int len, int caplen, const u_char* data, + int DataSent(double t, uint64 seq, int len, int caplen, const u_char* data, const IP_Hdr* ip, const struct tcphdr* tp); - void AckReceived(int seq); + void AckReceived(uint64 seq); void SetContentsFile(BroFile* f); BroFile* GetContentsFile() const { return contents_file; } @@ -139,20 +204,25 @@ public: int window_scale; // from the TCP option uint32 window_ack_seq; // at which ack_seq number did we record 'window' uint32 window_seq; // at which sending sequence number did we record 'window' - int contents_start_seq; // relative seq # where contents file starts - int FIN_seq; // relative seq # to start_seq + uint64 contents_start_seq; // relative seq # where contents file starts + uint64 FIN_seq; // relative seq # to start_seq int SYN_cnt, FIN_cnt, RST_cnt; int did_close; // whether we've reported it closing int is_orig; - // Sequence numbers associated with last control packets. + // Relative sequence numbers associated with last control packets. // Used to determine whether ones seen again are interesting, // for tracking history. - uint32 hist_last_SYN, hist_last_FIN, hist_last_RST; + uint64 hist_last_SYN, hist_last_FIN, hist_last_RST; protected: - uint32 start_seq, last_seq, ack_seq; // in host order - uint32 last_seq_high, ack_seq_high; + int64 start_seq; // Initial TCP sequence number in host order. + // Signed 64-bit to detect initial sequence wrapping. + // Use StartSeq() accessor if need it in terms of + // an absolute TCP sequence number. + uint32 last_seq, ack_seq; // in host order + uint32 seq_wraps, ack_wraps; // Number of times 32-bit TCP sequence space + // has wrapped around (overflowed). }; #define ENDIAN_UNKNOWN 0 diff --git a/src/analyzer/protocol/tcp/TCP_Reassembler.cc b/src/analyzer/protocol/tcp/TCP_Reassembler.cc index da8dd857fd..1fabfc5d73 100644 --- a/src/analyzer/protocol/tcp/TCP_Reassembler.cc +++ b/src/analyzer/protocol/tcp/TCP_Reassembler.cc @@ -14,11 +14,6 @@ using namespace analyzer::tcp; // Note, sequence numbers are relative. I.e., they start with 1. -// TODO: The Reassembler should start using 64 bit ints for keeping track of -// sequence numbers; currently they become negative once 2GB are exceeded. -// -// See #348 for more information. - const bool DEBUG_tcp_contents = false; const bool DEBUG_tcp_connection_close = false; const bool DEBUG_tcp_match_undelivered = false; @@ -44,9 +39,7 @@ TCP_Reassembler::TCP_Reassembler(analyzer::Analyzer* arg_dst_analyzer, deliver_tcp_contents = 0; skip_deliveries = 0; did_EOF = 0; -#ifdef ENABLE_SEQ_TO_SKIP seq_to_skip = 0; -#endif in_delivery = false; if ( tcp_contents ) @@ -73,12 +66,11 @@ TCP_Reassembler::~TCP_Reassembler() void TCP_Reassembler::Done() { - MatchUndelivered(-1); + MatchUndelivered(-1, true); if ( record_contents_file ) { // Record any undelivered data. - if ( blocks && - seq_delta(last_reassem_seq, last_block->upper) < 0 ) + if ( blocks && last_reassem_seq < last_block->upper ) RecordToSeq(last_reassem_seq, last_block->upper, record_contents_file); @@ -86,13 +78,13 @@ void TCP_Reassembler::Done() } } -void TCP_Reassembler::SizeBufferedData(int& waiting_on_hole, - int& waiting_on_ack) const +void TCP_Reassembler::SizeBufferedData(uint64& waiting_on_hole, + uint64& waiting_on_ack) const { waiting_on_hole = waiting_on_ack = 0; for ( DataBlock* b = blocks; b; b = b->next ) { - if ( seq_delta(b->seq, last_reassem_seq) <= 0 ) + if ( b->seq <= last_reassem_seq ) // We must have delivered this block, but // haven't yet trimmed it. waiting_on_ack += b->Size(); @@ -126,7 +118,7 @@ void TCP_Reassembler::SetContentsFile(BroFile* f) } -void TCP_Reassembler::Undelivered(int up_to_seq) +void TCP_Reassembler::Undelivered(uint64 up_to_seq) { TCP_Endpoint* endpoint = endp; TCP_Endpoint* peer = endpoint->peer; @@ -142,13 +134,7 @@ void TCP_Reassembler::Undelivered(int up_to_seq) // was a keep-alive. So, in either case, just ignore it. // TODO: Don't we need to update last_reassm_seq ???? - if ( up_to_seq >=0 ) - // Since seq are currently only 32 bit signed - // integers, they will become negative if a - // connection has more than 2GB of data. Remove the - // above if and always return here, once we're using - // 64 bit ints - return; + return; } #if 0 @@ -156,15 +142,14 @@ void TCP_Reassembler::Undelivered(int up_to_seq) { // Make sure we're not worrying about undelivered // FIN control octets! - int FIN_seq = endpoint->FIN_seq - endpoint->start_seq; - if ( seq_delta(up_to_seq, FIN_seq) >= 0 ) - up_to_seq = FIN_seq - 1; + if ( up_to_seq >= endpoint->FIN_seq ) + up_to_seq = endpoint->FIN_seq - 1; } #endif if ( DEBUG_tcp_contents ) { - DEBUG_MSG("%.6f Undelivered: IsOrig()=%d up_to_seq=%d, last_reassm=%d, " + DEBUG_MSG("%.6f Undelivered: IsOrig()=%d up_to_seq=%"PRIu64", last_reassm=%"PRIu64", " "endp: FIN_cnt=%d, RST_cnt=%d, " "peer: FIN_cnt=%d, RST_cnt=%d\n", network_time, IsOrig(), up_to_seq, last_reassem_seq, @@ -172,7 +157,7 @@ void TCP_Reassembler::Undelivered(int up_to_seq) peer->FIN_cnt, peer->RST_cnt); } - if ( seq_delta(up_to_seq, last_reassem_seq) <= 0 ) + if ( up_to_seq <= last_reassem_seq ) // This should never happen. (Reassembler::TrimToSeq has the only call // to this method and only if this condition is not true). reporter->InternalError("Calling Undelivered for data that has already been delivered (or has already been marked as undelivered"); @@ -195,10 +180,10 @@ void TCP_Reassembler::Undelivered(int up_to_seq) { if ( DEBUG_tcp_contents ) { - DEBUG_MSG("%.6f Undelivered: IsOrig()=%d, seq=%d, len=%d, " + DEBUG_MSG("%.6f Undelivered: IsOrig()=%d, seq=%"PRIu64", len=%"PRIu64", " "skip_deliveries=%d\n", network_time, IsOrig(), last_reassem_seq, - seq_delta(up_to_seq, last_reassem_seq), + up_to_seq - last_reassem_seq, skip_deliveries); } @@ -210,8 +195,8 @@ void TCP_Reassembler::Undelivered(int up_to_seq) // packet, but it's undelievered because it's out of // sequence. - int seq = last_reassem_seq; - int len = seq_delta(up_to_seq, last_reassem_seq); + 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 @@ -255,19 +240,19 @@ void TCP_Reassembler::Undelivered(int up_to_seq) RecordToSeq(last_reassem_seq, up_to_seq, record_contents_file); if ( tcp_match_undelivered ) - MatchUndelivered(up_to_seq); + MatchUndelivered(up_to_seq, false); // But we need to re-adjust last_reassem_seq in either case. last_reassem_seq = up_to_seq; // we've done our best ... } -void TCP_Reassembler::MatchUndelivered(int up_to_seq) +void TCP_Reassembler::MatchUndelivered(uint64 up_to_seq, bool use_last_upper) { if ( ! blocks || ! rule_matcher ) return; ASSERT(last_block); - if ( up_to_seq == -1 ) + if ( use_last_upper ) up_to_seq = last_block->upper; // ### Note: the original code did not check whether blocks have @@ -277,36 +262,35 @@ void TCP_Reassembler::MatchUndelivered(int up_to_seq) // We are to match any undelivered data, from last_reassem_seq to // min(last_block->upper, up_to_seq). // Is there such data? - if ( seq_delta(up_to_seq, last_reassem_seq) <= 0 || - seq_delta(last_block->upper, last_reassem_seq) <= 0 ) + if ( up_to_seq <= last_reassem_seq || + last_block->upper <= last_reassem_seq ) return; // Skip blocks that are already delivered (but not ACK'ed). // Question: shall we instead keep a pointer to the first undelivered // block? DataBlock* b; - for ( b = blocks; b && seq_delta(b->upper, last_reassem_seq) <= 0; - b = b->next ) + for ( b = blocks; b && b->upper <= last_reassem_seq; b = b->next ) tcp_analyzer->Conn()->Match(Rule::PAYLOAD, b->block, b->Size(), false, false, IsOrig(), false); ASSERT(b); } -void TCP_Reassembler::RecordToSeq(int start_seq, int stop_seq, BroFile* f) +void TCP_Reassembler::RecordToSeq(uint64 start_seq, uint64 stop_seq, BroFile* f) { DataBlock* b = blocks; // Skip over blocks up to the start seq. - while ( b && seq_delta(b->upper, start_seq) <= 0 ) + while ( b && b->upper <= start_seq ) b = b->next; if ( ! b ) return; - int last_seq = start_seq; - while ( b && seq_delta(b->upper, stop_seq) <= 0 ) + uint64 last_seq = start_seq; + while ( b && b->upper <= stop_seq ) { - if ( seq_delta(b->seq, last_seq) > 0 ) + if ( b->seq > last_seq ) RecordGap(last_seq, b->seq, f); RecordBlock(b, f); @@ -316,7 +300,7 @@ void TCP_Reassembler::RecordToSeq(int start_seq, int stop_seq, BroFile* f) if ( b ) // Check for final gap. - if ( seq_delta(last_seq, stop_seq) < 0 ) + if ( last_seq < stop_seq ) RecordGap(last_seq, stop_seq, f); } @@ -337,9 +321,9 @@ void TCP_Reassembler::RecordBlock(DataBlock* b, BroFile* f) } } -void TCP_Reassembler::RecordGap(int start_seq, int upper_seq, BroFile* f) +void TCP_Reassembler::RecordGap(uint64 start_seq, uint64 upper_seq, BroFile* f) { - if ( f->Write(fmt("\n<>\n", seq_delta(upper_seq, start_seq))) ) + if ( f->Write(fmt("\n<>\n", upper_seq - start_seq)) ) return; reporter->Error("TCP_Reassembler contents gap write failed"); @@ -356,8 +340,8 @@ void TCP_Reassembler::RecordGap(int start_seq, int upper_seq, BroFile* f) void TCP_Reassembler::BlockInserted(DataBlock* start_block) { - if ( seq_delta(start_block->seq, last_reassem_seq) > 0 || - seq_delta(start_block->upper, last_reassem_seq) <= 0 ) + if ( start_block->seq > last_reassem_seq || + start_block->upper <= last_reassem_seq ) return; // We've filled a leading hole. Deliver as much as possible. @@ -367,12 +351,12 @@ void TCP_Reassembler::BlockInserted(DataBlock* start_block) // loop we have to take care not to deliver already-delivered // data. for ( DataBlock* b = start_block; - b && seq_delta(b->seq, last_reassem_seq) <= 0; b = b->next ) + b && b->seq <= last_reassem_seq; b = b->next ) { if ( b->seq == last_reassem_seq ) { // New stuff. - int len = b->Size(); - int seq = last_reassem_seq; + uint64 len = b->Size(); + uint64 seq = last_reassem_seq; last_reassem_seq += len; @@ -406,10 +390,10 @@ void TCP_Reassembler::BlockInserted(DataBlock* start_block) // TCP_Connection::NextPacket. } -void TCP_Reassembler::Overlap(const u_char* b1, const u_char* b2, int n) +void TCP_Reassembler::Overlap(const u_char* b1, const u_char* b2, uint64 n) { if ( DEBUG_tcp_contents ) - DEBUG_MSG("%.6f TCP contents overlap: %d IsOrig()=%d\n", network_time, n, IsOrig()); + DEBUG_MSG("%.6f TCP contents overlap: %"PRIu64" IsOrig()=%d\n", network_time, n, IsOrig()); if ( rexmit_inconsistency && memcmp((const void*) b1, (const void*) b2, n) && @@ -438,7 +422,7 @@ bool TCP_Reassembler::DoUnserialize(UnserialInfo* info) return false; // Cannot be reached. } -void TCP_Reassembler::Deliver(int seq, int len, const u_char* data) +void TCP_Reassembler::Deliver(uint64 seq, int len, const u_char* data) { if ( type == Direct ) dst_analyzer->NextStream(len, data, IsOrig()); @@ -446,24 +430,24 @@ void TCP_Reassembler::Deliver(int seq, int len, const u_char* data) dst_analyzer->ForwardStream(len, data, IsOrig()); } -int TCP_Reassembler::DataSent(double t, int seq, int len, +int TCP_Reassembler::DataSent(double t, uint64 seq, int len, const u_char* data, bool replaying) { - int ack = seq_delta(endp->AckSeq(), endp->StartSeq()); - int upper_seq = seq + len; + uint64 ack = endp->ToRelativeSeqSpace(endp->AckSeq(), endp->AckWraps()); + uint64 upper_seq = seq + len; if ( DEBUG_tcp_contents ) { - DEBUG_MSG("%.6f DataSent: IsOrig()=%d seq=%d upper=%d ack=%d\n", + DEBUG_MSG("%.6f DataSent: IsOrig()=%d seq=%"PRIu64" upper=%"PRIu64" ack=%"PRIu64"\n", network_time, IsOrig(), seq, upper_seq, ack); } if ( skip_deliveries ) return 0; - if ( seq_delta(seq, ack) < 0 && ! replaying ) + if ( seq < ack && ! replaying ) { - if ( seq_delta(upper_seq, ack) <= 0 ) + if ( upper_seq <= ack ) // We've already delivered this and it's been acked. return 0; @@ -472,7 +456,7 @@ int TCP_Reassembler::DataSent(double t, int seq, int len, // packet held [a, a+b) and this packet holds [a, a+c) for c>b // (which some TCP's will do when retransmitting). Trim the // packet to just the unacked data. - int amount_acked = seq_delta(ack, seq); + uint64 amount_acked = ack - seq; seq += amount_acked; data += amount_acked; len -= amount_acked; @@ -500,16 +484,13 @@ int TCP_Reassembler::DataSent(double t, int seq, int len, } -void TCP_Reassembler::AckReceived(int seq) +void TCP_Reassembler::AckReceived(uint64 seq) { - if ( endp->FIN_cnt > 0 && seq_delta(seq, endp->FIN_seq) >= 0 ) - // TrimToSeq: FIN_seq - 1 + if ( endp->FIN_cnt > 0 && seq >= endp->FIN_seq ) seq = endp->FIN_seq - 1; - int bytes_covered = seq_delta(seq, trim_seq); - - if ( bytes_covered <= 0 ) - // Zero, or negative in sequence-space terms. Nothing to do. + if ( seq <= trim_seq ) + // Nothing to do. return; bool test_active = ! skip_deliveries && ! tcp_analyzer->Skipping() && @@ -517,12 +498,12 @@ void TCP_Reassembler::AckReceived(int seq) (endp->state == TCP_ENDPOINT_ESTABLISHED && endp->peer->state == TCP_ENDPOINT_ESTABLISHED ) ); - int num_missing = TrimToSeq(seq); + uint64 num_missing = TrimToSeq(seq); if ( test_active ) { ++tot_ack_events; - tot_ack_bytes += bytes_covered; + tot_ack_bytes += seq - trim_seq; if ( num_missing > 0 ) { @@ -602,20 +583,18 @@ void TCP_Reassembler::CheckEOF() // Deliver, DeliverBlock is not virtual, and this allows us to insert // operations that apply to all connections using TCP_Contents. -void TCP_Reassembler::DeliverBlock(int seq, int len, const u_char* data) +void TCP_Reassembler::DeliverBlock(uint64 seq, int len, const u_char* data) { -#ifdef ENABLE_SEQ_TO_SKIP - if ( seq_delta(seq + len, seq_to_skip) <= 0 ) + if ( seq + len <= seq_to_skip ) return; - if ( seq_delta(seq, seq_to_skip) < 0 ) + if ( seq < seq_to_skip ) { - int to_skip = seq_delta(seq_to_skip, seq); + uint64 to_skip = seq_to_skip - seq; len -= to_skip; data += to_skip; seq = seq_to_skip; } -#endif if ( deliver_tcp_contents ) { @@ -640,23 +619,21 @@ void TCP_Reassembler::DeliverBlock(int seq, int len, const u_char* data) in_delivery = true; Deliver(seq, len, data); in_delivery = false; -#ifdef ENABLE_SEQ_TO_SKIP - if ( seq_delta(seq + len, seq_to_skip) < 0 ) + + if ( seq + len < seq_to_skip ) SkipToSeq(seq_to_skip); -#endif + } -#ifdef ENABLE_SEQ_TO_SKIP -void TCP_Reassembler::SkipToSeq(int seq) +void TCP_Reassembler::SkipToSeq(uint64 seq) { - if ( seq_delta(seq, seq_to_skip) > 0 ) + if ( seq > seq_to_skip ) { seq_to_skip = seq; if ( ! in_delivery ) TrimToSeq(seq); } } -#endif int TCP_Reassembler::DataPending() const { @@ -665,20 +642,28 @@ int TCP_Reassembler::DataPending() const if ( skip_deliveries ) return 0; - uint32 delivered_seq = Endpoint()->StartSeq() + DataSeq(); + uint64 delivered_seq = Endpoint()->StartSeqI64() + DataSeq(); + uint64 last_seq = TCP_Endpoint::ToFullSeqSpace(Endpoint()->LastSeq(), + Endpoint()->SeqWraps()); + + if ( last_seq < delivered_seq ) + return 0; // Q. Can we say that? - // ASSERT(delivered_seq <= Endpoint()->LastSeq()); + // ASSERT(delivered_seq <= last_seq); // - // A. Yes, but only if we express it with 64-bit comparison - // to handle sequence wrapping around. (Or perhaps seq_delta - // is enough here?) + // A. That should be true if endpoints are always initialized w/ + // trustworthy sequence numbers, though it seems that may not currently + // be the case. e.g. a RST packet may end up initializing the endpoint. + // In that case, maybe there's not any "right" way to initialize it, so + // the check for last_seq < delivered_seq sort of serves as a check for + // endpoints that weren't initialized w/ meaningful sequence numbers. // We've delivered everything if we're up to the penultimate // sequence number (since a FIN consumes an octet in the // sequence space), or right at it (because a RST does not). - if ( delivered_seq != Endpoint()->LastSeq() - 1 && - delivered_seq != Endpoint()->LastSeq() ) + if ( delivered_seq != last_seq - 1 && + delivered_seq != last_seq ) return 1; // If we've sent RST, then we can't send ACKs any more. diff --git a/src/analyzer/protocol/tcp/TCP_Reassembler.h b/src/analyzer/protocol/tcp/TCP_Reassembler.h index e3dcf82a1b..3dfe75bf10 100644 --- a/src/analyzer/protocol/tcp/TCP_Reassembler.h +++ b/src/analyzer/protocol/tcp/TCP_Reassembler.h @@ -4,13 +4,6 @@ #include "Reassem.h" #include "TCP_Endpoint.h" -// The skip_to_seq feature does not work correctly with connections >2GB due -// to use of 32 bit signed ints (see comments in TCP_Reassembler.cc) Since -// it's not used by any analyzer or policy script we disable it. Could be -// added back in once we start using 64bit integers. -// -// #define ENABLE_SEQ_TO_SKIP - class BroFile; class Connection; @@ -48,12 +41,12 @@ public: // // If we're not processing contents, then naturally each of // these is empty. - void SizeBufferedData(int& waiting_on_hole, int& waiting_on_ack) const; + 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). - int NumUndeliveredBytes() const + uint64 NumUndeliveredBytes() const { if ( last_block ) return last_block->upper - last_reassem_seq; @@ -64,19 +57,15 @@ public: void SetContentsFile(BroFile* f); BroFile* GetContentsFile() const { return record_contents_file; } - void MatchUndelivered(int up_to_seq = -1); + void MatchUndelivered(uint64 up_to_seq, bool use_last_upper); -#ifdef ENABLE_SEQ_TO_SKIP // Skip up to seq, as if there's a content gap. // Can be used to skip HTTP data for performance considerations. - void SkipToSeq(int seq); -} } // namespace analyzer::* + void SkipToSeq(uint64 seq); -#endif - - int DataSent(double t, int seq, int len, const u_char* data, + int DataSent(double t, uint64 seq, int len, const u_char* data, bool replaying=true); - void AckReceived(int seq); + void AckReceived(uint64 seq); // Checks if we have delivered all contents that we can possibly // deliver for this endpoint. Calls TCP_Analyzer::EndpointEOF() @@ -86,35 +75,32 @@ public: int HasUndeliveredData() const { return HasBlocks(); } int HadGap() const { return had_gap; } int DataPending() const; - int DataSeq() const { return LastReassemSeq(); } + uint64 DataSeq() const { return LastReassemSeq(); } - void DeliverBlock(int seq, int len, const u_char* data); - virtual void Deliver(int seq, int len, const u_char* data); + 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(); } -#ifdef ENABLE_SEQ_TO_SKIP - bool IsSkippedContents(int seq, int length) const - { return seq + length <= seq_to_skip; } -} } // namespace analyzer::* -#endif + bool IsSkippedContents(uint64 seq, int length) const + { return seq + length <= seq_to_skip; } private: TCP_Reassembler() { } DECLARE_SERIAL(TCP_Reassembler); - void Undelivered(int up_to_seq); + void Undelivered(uint64 up_to_seq); - void RecordToSeq(int start_seq, int stop_seq, BroFile* f); + void RecordToSeq(uint64 start_seq, uint64 stop_seq, BroFile* f); void RecordBlock(DataBlock* b, BroFile* f); - void RecordGap(int start_seq, int upper_seq, 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, int n); + void Overlap(const u_char* b1, const u_char* b2, uint64 n); TCP_Endpoint* endp; @@ -123,9 +109,8 @@ private: unsigned int did_EOF:1; unsigned int skip_deliveries:1; -#ifdef ENABLE_SEQ_TO_SKIP - int seq_to_skip; -#endif + uint64 seq_to_skip; + bool in_delivery; BroFile* record_contents_file; // file on which to reassemble contents diff --git a/src/analyzer/protocol/tcp/events.bif b/src/analyzer/protocol/tcp/events.bif index cac18bfa3e..f52fadaebb 100644 --- a/src/analyzer/protocol/tcp/events.bif +++ b/src/analyzer/protocol/tcp/events.bif @@ -223,9 +223,10 @@ event connection_EOF%(c: connection, is_orig: bool%); ## corresponds to one set flag, as follows: ``S`` -> SYN; ``F`` -> FIN; ## ``R`` -> RST; ``A`` -> ACK; ``P`` -> PUSH. ## -## seq: The packet's TCP sequence number. +## seq: The packet's relative TCP sequence number. ## -## ack: The packet's ACK number. +## ack: If the ACK flag is set for the packet, the packet's relative ACK +## number, else zero. ## ## len: The length of the TCP payload, as specified in the packet header. ## diff --git a/src/analyzer/protocol/teredo/Teredo.cc b/src/analyzer/protocol/teredo/Teredo.cc index d81f90d840..400f38839e 100644 --- a/src/analyzer/protocol/teredo/Teredo.cc +++ b/src/analyzer/protocol/teredo/Teredo.cc @@ -140,7 +140,7 @@ RecordVal* TeredoEncapsulation::BuildVal(const IP_Hdr* inner) const } void Teredo_Analyzer::DeliverPacket(int len, const u_char* data, bool orig, - int seq, const IP_Hdr* ip, int caplen) + uint64 seq, const IP_Hdr* ip, int caplen) { Analyzer::DeliverPacket(len, data, orig, seq, ip, caplen); diff --git a/src/analyzer/protocol/teredo/Teredo.h b/src/analyzer/protocol/teredo/Teredo.h index 0da007187d..68dfb8bb73 100644 --- a/src/analyzer/protocol/teredo/Teredo.h +++ b/src/analyzer/protocol/teredo/Teredo.h @@ -19,7 +19,7 @@ public: virtual void Done(); virtual void DeliverPacket(int len, const u_char* data, bool orig, - int seq, const IP_Hdr* ip, int caplen); + uint64 seq, const IP_Hdr* ip, int caplen); static analyzer::Analyzer* InstantiateAnalyzer(Connection* conn) { return new Teredo_Analyzer(conn); } diff --git a/src/analyzer/protocol/udp/UDP.cc b/src/analyzer/protocol/udp/UDP.cc index 4c26ae5d99..36d5831a6a 100644 --- a/src/analyzer/protocol/udp/UDP.cc +++ b/src/analyzer/protocol/udp/UDP.cc @@ -38,7 +38,7 @@ void UDP_Analyzer::Done() } void UDP_Analyzer::DeliverPacket(int len, const u_char* data, bool is_orig, - int seq, const IP_Hdr* ip, int caplen) + uint64 seq, const IP_Hdr* ip, int caplen) { assert(ip); diff --git a/src/analyzer/protocol/udp/UDP.h b/src/analyzer/protocol/udp/UDP.h index bcfee401b0..792f83de8a 100644 --- a/src/analyzer/protocol/udp/UDP.h +++ b/src/analyzer/protocol/udp/UDP.h @@ -28,7 +28,7 @@ public: protected: virtual void Done(); virtual void DeliverPacket(int len, const u_char* data, bool orig, - int seq, const IP_Hdr* ip, int caplen); + uint64 seq, const IP_Hdr* ip, int caplen); virtual bool IsReuse(double t, const u_char* pkt); virtual unsigned int MemoryAllocation() const; diff --git a/src/net_util.h b/src/net_util.h index e5dbbcdae2..0f34335267 100644 --- a/src/net_util.h +++ b/src/net_util.h @@ -119,7 +119,7 @@ struct ip6_rthdr { // True if sequence # a is between b and c (b <= a <= c). It must be true // that b <= c in the sequence space. -inline int seq_between(uint32 a, uint32 b, uint32 c) +inline bool seq_between(uint32 a, uint32 b, uint32 c) { if ( b <= c ) return a >= b && a <= c; @@ -128,9 +128,9 @@ inline int seq_between(uint32 a, uint32 b, uint32 c) } // Returns a - b, adjusted for sequence wraparound. -inline int seq_delta(uint32 a, uint32 b) +inline int32 seq_delta(uint32 a, uint32 b) { - return int(a-b); + return a - b; } class IPAddr; diff --git a/testing/btest/Baseline/core.tcp.large-file-reassembly/conn.log b/testing/btest/Baseline/core.tcp.large-file-reassembly/conn.log new file mode 100644 index 0000000000..c76f4dd03b --- /dev/null +++ b/testing/btest/Baseline/core.tcp.large-file-reassembly/conn.log @@ -0,0 +1,12 @@ +#separator \x09 +#set_separator , +#empty_field (empty) +#unset_field - +#path conn +#open 2014-04-09-16-44-53 +#fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p proto service duration orig_bytes resp_bytes conn_state local_orig missed_bytes history orig_pkts orig_ip_bytes resp_pkts resp_ip_bytes tunnel_parents +#types time string addr port addr port enum string interval count count string bool count string count count count count set[string] +1395939406.175845 CjhGID4nQcgTWjvg4c 192.168.56.1 59763 192.168.56.101 63988 tcp ftp-data 0.001676 0 270 SF - 0 ShAdfFa 5 272 4 486 (empty) +1395939411.361078 CCvvfg3TEfuqmmG4bh 192.168.56.1 59764 192.168.56.101 37150 tcp ftp-data 150.496065 0 5416666670 SF - 4675708816 ShAdfFa 13 688 12 24454 (empty) +1395939399.984671 CXWv6p3arKYeMETxOg 192.168.56.1 59762 192.168.56.101 21 tcp ftp 169.634297 104 1041 SF - 0 ShAdDaFf 31 1728 18 1985 (empty) +#close 2014-04-09-16-44-54 diff --git a/testing/btest/Baseline/core.tcp.large-file-reassembly/files.log b/testing/btest/Baseline/core.tcp.large-file-reassembly/files.log new file mode 100644 index 0000000000..b8b9bf9db1 --- /dev/null +++ b/testing/btest/Baseline/core.tcp.large-file-reassembly/files.log @@ -0,0 +1,11 @@ +#separator \x09 +#set_separator , +#empty_field (empty) +#unset_field - +#path files +#open 2014-04-09-16-44-53 +#fields ts fuid tx_hosts rx_hosts conn_uids source depth analyzers mime_type filename duration local_orig is_orig seen_bytes total_bytes missing_bytes overflow_bytes timedout parent_fuid md5 sha1 sha256 extracted +#types time string set[addr] set[addr] set[string] string count set[string] string string interval bool bool count count count count bool string string string string string +1395939406.177079 FAb5m22Dhe2Zi95anf 192.168.56.101 192.168.56.1 CjhGID4nQcgTWjvg4c FTP_DATA 0 DATA_EVENT text/plain - 0.000000 - F 270 - 0 0 F - - - - - +1395939411.364462 FhI0ao2FNTjabdfSBd 192.168.56.101 192.168.56.1 CCvvfg3TEfuqmmG4bh FTP_DATA 0 DATA_EVENT text/plain - 150.490904 - F 23822 - 5416642848 0 F - - - - - +#close 2014-04-09-16-44-54 diff --git a/testing/btest/Baseline/core.tcp.large-file-reassembly/out b/testing/btest/Baseline/core.tcp.large-file-reassembly/out new file mode 100644 index 0000000000..dd3960bdb7 --- /dev/null +++ b/testing/btest/Baseline/core.tcp.large-file-reassembly/out @@ -0,0 +1,11 @@ +file_chunk, 270, 0, drwxr-xr-x 3 0 0 4096 Mar 27 11:55 .^M^Jdrwxr-xr-x 3 0 0 4096 Mar 27 11:55 ..^M^Jdrwxr-xr-x 2 0 0 4096 Mar 27 11:43 pub^M^J-rw-rw-r-- 1 1000 1000 5416666670 Mar 27 11:52 rand.txt^M^J +file_chunk, 14480, 0, TCf8ZQLH67eBQks8SjFaumquAt7f9eg6GNvyLgvdbRl4QShP5o47kdBupR8IxbCz^JZ1sR200ZDSWX1TeH7UVjxBg+eQ8YpmUbnjqePKMUBbb0uq6tDGYGauJiZnSHVNez^JVZmm+pCPVdIGyWe27Xgub9s8PyDBjVD3amDxvoFb8ad86eTDcrzuPZ0/iFP4CnDY^JHFLAvEbvgBVuKTmveyUjmis9nRgvjaeoHhBV7/XtC6fP9ayGCHqJIYs7pGHEm0hi^Ji95bgfyFCEB2hBvwGGNQStTigpE89eURtsmxnK+I3Hxk+dyBQjQ6hTxQlwmqZuto^J/ZMEv8KCfrZUtTh4s3l621DN7wRiUbgltFXAIoaWwc5YACR65582L9aEX86XVNXt^J8IfLL0klmNgaRO49b1He7exMUA0UCUY9DFdFfqyt2hMoPJqEfm4nRH0x/xQs5x/G^Jq5K+JPJtkyxvqI7AwMSRaN+k7ez12fZCwzpPIU8taS++y0op+kmXsPaTSJpPe8Ev^Js1XyutkfH5OPmrt413q80e4UTlV73zGs8XMBO+VL+Jb+0IUNnmiyWzqIuYokI9RS^JCdLbWCdLGGb6+k76rY4oIDnUbAP7YCDdr2s3QZ9aLMNaSpuyKY19WNzNbw8cI81O^JIuTY6C3NzXMItjWriqAzmMl2AXztrPZZ2GFhyUy1Hwf4DufBEVeDMvhVd+WlfzVn^JlRdy8Os5X0ULPhFDmej+1igX/AD9a2Yf26vqak8AUvLbJciJWFZp17sZYXus6zos^JR17iUaq63Mfl0dk6wnktVLIGt6EHBYb/oJ65ZGLMuFSDqv+NvVhuyNd/IIR4tUKO^JqNVH/+FHHqjbpZQvFHSTqOGA62rb1AecBRnliYKjRTsg7u4/HI+v/jwPnp89pntJ^JkztVIkc7VVG0GhvgnKFjmV+bVddG3UpB3juIVMJwcFOFnQNzF0hm7oDdfEYXEUht^JW/TCpIox9O+VQknCTo4iZcZOOXGkEYRc11C+P2WPk46b2OER/l8agJPG9qS6Yf35^J+ljLAVFNgW12iqiqCYmfQM6z1l+6RIo/DlDSALbhYjTV9CG02WwyQiG4WpkAHnx+^JiaSwwrKYCklvFoUtisVGfV19rTo1HGGG2FFo5oCY4BPmbIQWidTXJtA1JkHsni5R^JPlG8elgJkTJJKkzdwAh5V0UL+m1y2zH+NyQHFzj9zunB0g5QEmuYMt18TvXy7D/W^JkgJbWGvDCKY36ZKVhWTTqsgQ2xecH+vKBaCF4IofA0joodZzBv9GH6UOSkhTML57^J5BRbLoPr3IqbTAx7PFlixb+fIur2UeUo+RYZeDudo7HmvLBnsGFw0K9rBVNg1D8C^JwcO4lpwxZEPsLeqKChpHpQugpkfSnC9B2/Oywoep2FAI2OL4zL9nOWb+QnE8kibe^JmZVCAm6p2qnr1nfKMUP2YWKbTeyowi6dlS9SfQdzc5+a1Asg/+S8ZWOPDJGauS6h^JNrfV2HRoHwYmpqvxN3/8A7vkF+rPgx1yeGHK0mDVn4F2ke1E+r5e1F9IZzM90EkR^JFX1hEcNcqzPX/rerGjD6WNBDdoAvmsth8mrcsIf0iq/yvNblB9R4Vg1+bxHYOXYf^JE70vkvtaSmWCQ5gi19SYK01XR42Jnu+cnUtuCr3P2relXC5TjBqz3V2CO3St9tX/^J8sdKZWDc/kHAQ5uVZAIonoVp6Ffeu2Zz3B0NFjJj9hyJtLIJ+Qg2Bru0YeplIIQz^Jw8WXZ3xHw7nN2pIMRMkef8pAoonGsrUySUhhSjEMZCYDXvWpTSrOwm+LRsyJ9czy^J4kUBxgoiCdxGi0NpljEzvrj27ElBmqa2E/bOoK39ff89GSBvXeHw6NVrrDZhEFrU^JfnALNwjCGdxCrkPm2sw03cdsPRVO0yQppyYbT8MhWuzlq31VGps+EiwfpU+jHsw2^J7CuI4qC/n6yui5irPTV+GJmS900rfqCDab+PW6XJ82rGAN1lvV7+lz/x3lGcFCux^JUudDhQANxzHwTQGmwJeR4Fk+PGTAvQoWfgN+21hgPgIW4Yug1uKtL5IOK2rRVMTf^JljjxQ8FlEfZLdLZgiOOHnpioRz4n/SbcSMw15i9GHMmHE3wOmV7En11vBFPmUcYb^J+d2UaodnxE6psPmSfawBFI6TNT9fKaZchANali9OdFieh79e/7mox79DrzX4tuQT^JNLs1nj0jb+4Tm+LNqkJ5cvDkyFds0FbBd3CblDHNtdkIcSVj3TpkYz1wwYYogt7r^JV6wVmRQ09dhDmRSM8kVinGhVudTpBRH6+F922anxF9exYYKfYi7M/ODjuQLRCK7R^JwSNg7BDBVXt/Q31ryukAzcE5UtCk0LSlci02B1taq2Bp1ChFDpSzaqeshwgCQvYJ^JVLBPFdy21eqa8IQwXZ3wU2TEiGgJIv3k6M07uSDMCJF8/IPf7KmmOy/dotWXWSCe^J9FqYiGMYW5KRrTZnknhS2JYhC4iIHqlGYFYd5cSm3dtx6m1Y4hmqE4+JWRDK2I/s^JCkDbfOvU8UwES3k4tHORdqDn/b54EdEbnG06hfcg2B5FEg7cr90Qjdh838ldIcwG^JI0k9UewaVjjPL1dG585WFMQa3bZChzNN25kRGMQP24BGvA8wuKDseza7rn1dmrYw^JCRSsA2U7gNy96DKQFQX6Ga9uT9OCW+Ukvq2sejhL5cgiqZ6xZpV3WCFlFEjHEZDU^J/Jcaes5cbbkWLHe9PXwlLeCArWkwsrwhM/zS2vWN9xnvPzyYAaDqSlOPNeyBYW0t^JwEca4eu9Kg7dLNrZ8S6tEECdpor+9EAU6T8o60s20nUzmqG96yWhdl1mns+IHW8N^JwJ9u1uYlEKoAHPVdYY6MnWToAxH5KI1OaEfJ4He929/QGkIso6gRRyWlF2shqR+W^Jx74nIGsLeou4Ao8WGVjV0aa1qZiNw5KSB5QB5UuKlmTWG/gdk1APdsmudyg+Vc1T^JAXLdMwj7uvngrIZxFxqipXnWB7FPC4yzeiPu8qOoestmuqkhkD0FPCW5QFhk965F^Jxm9fqwgJPsjBTC5YTB2LOfTO5ZYdJiPYQmETOOe4a9ztL6HwQ2Y/zxc7GD4AbwQp^JM/AbXtIaCYgNkeG9vkJaLn6byDwdmJUZGHHNVjZca8wV6+YlboGrAYrJbX+ndyqH^JKquD7o1PkJTO+4H04lDmYquf/fRembQ51YGyVQaNqbLF1mbyfVd/lc+JJICTVT/o^Ju4+9yTKOhJG2Gb1DmBG+jOIuZkGv6m9CqZYfKTtDv9zwkUeNHMGcAX6n+TPc2WPI^JsBSKIdYnzlvRCMI9BJAWoNej5yQzzfCPlXd15Og+SK0mfM8+44iDRv/051rLVhcI^JCxQpRjq/NdINYF+WwwDoN4VlpPXLZkw1+qYoSHdstDiHv7uhRgP+cEbZXH8mDpe1^Jkj47aUHCLiGP8u1UgRXGH8A0jFp5yPEFU3SBePIehSZZynNB8u04mRpXc1kIlubA^JqnhGKpscdIZnO7KB7pQA2qF+s1I45amehPIBDBzbaGkMJe2Esqphgh3Rk695uPDm^JQM7JjrfhBTlNXxoxC48WdbI9+xzhTavuwP4BhUNADgDel9vxs+HkT1rLR907NaN1^JxWJdo2bsRFNdftSKf2XCthor9VHwOmyU0XI2yeVSxu9hdA1jK4M4C7fmRrQrwuoO^JS6fTlgbMeTey2ZHrJO/iDT+9sGfgT/oGDXYzZrbaFbiBRj5HLweXE+rAyIG77yUY^JZEqkeh1BA1KHSxqhXmkrYr+ambErzrQHIr6fTujmPVc5W1kIZEAhMdLDJ8U/C1dL^JjqjEA/VyjJr8A2gELABBiATb5ro485x/GdUHgOam0sYpHqG4wmsxnM8iVuxbwlS5^JC9z/MjVvBoLl83/YZjG1jfRLkaX6wzWXuSeybIDk7TilDwAdeFAbUfgEqH5xnXND^JPHnSaA8yOxba7kpuRDWJebGb2GPxiP6u0Wk8iXd3jnSJdE3+b69SXzgM82Wht6NH^JFkBEQWf8hDu0pAhxxU32yPCrLoRxCpl/K/p1cL01xtzDbj5Ncfhg5TbYYUyRw2UN^JSHQ46bN/ozKIQ02T+bhA7Z4BVjVw3Fens8jbZX+Z5ClnEiY5q4g+hR6estFTli3z^J0bQBij3OB0yseeOCcyLt9ZpepxQwgO6BNvecNuNtBwEq/xCx7ESzX3N7dVZAjWKE^JdyjbFMIPKMfIMlfU7wvuaxiyWkbVsBcPDPcyLja3qzO85GZgh0Uln+mCModfqZc/^JcplyVPYQBIFXAViGIFZONpAOWC29fy4j0uRsNYKKhRv6fSZzVNbVgeljKFwTCAXu^J8CtcxnpNOTYXuGZbgISo6oHxCy+fIK1Q14eaZepMWWYT22kWR7FlN4BOLcj50K/Z^JBxpcOexNb0QreketOWPWfHflY9YxB07ykX6djOH9ZOlITbZ0c2BMxfJxOaaNbidn^JX1Vka0i06Sk2iFw2MmxHJm5zwN6Ln4S9hCrwaPCDkmXOCoN0pr1jt9teBBA/LkDG^Jn+rp2U4CwSAtJy690+HlZ+Ni/m5QkchnSsGuYXeBE7feao+dBTJ5hyFpMKjjyOS3^Jf+vZkyNxOzgugBnQ5e0suK46y5GhpbrmNIbP8lJn04B6CFe/lidABVS50GK5LqCD^JtdtAyr+6LD0PCJU2pJeqwePqlbQmA5XZxOW1vJVNQJ4EEJfcJj8Ha2hynAOQaiT/^JAXtlD22EXutFfFgFBgkFJZ35+nO4TuSIawad8xkIBnpMX87wpp4nVi3aWd4sMr0o^JyXWSHcd3Y+izqfXH/6BqlUeXNGQjLlj7biMCosz3iFBRhOvUK1a5r90ZcVy+8+Ty^J4qT52tO7+bQOngxBiwqpnvKAONsxFFHWgR7/LjYbYKtgtq+1ibACiaSzQg+IVFP3^J1V7aZb9fZP0YBvbhv4JxdTXxFfJ4knugi+5mmm1PIyznXWnsWOEbYEnZV4dZIq5M^JQqBIYxrS+aWnUyE8DTsXqDUwVL/rBjbhK/1RxNT+mzHG7Q/phD3y2d8ysHlmAWfl^JDGZbZ8+Plpm7uhj/fK6b6FqYO9qJYoTSesyEsZ0Pfjb7uMrYjSbRyRg6yTuV3Qe+^Jjz+g9Nj63cFMlXVlvaBZgwu8giF/SmdkTM48IVc8BkeMJlPg0fnqcEbEgnMrYBsG^Jv8FdEUWTWvzoDFCiQRFrSnPF8GIBcwgrxN7wGqWexfQlzQsQ9XbJlACIwKMLzh2t^JQTr0zs9g8yAk9SQMahWtYJG4IPdAI0mH9dBSYzt0ATxtBe3NpAhrewtcNqTBnII5^JhUcSoygg4JGCBjxZpxle7/anr4CBduMHcAiL9JFCcWb/cg8uwFPm8p+Ddsz+e3ir^J5WZPHa8uXRupG0ZIY3kQXebizwq6aULjDSFy+ggEWHlkGHIAUYpvKXmCiQAWiKiP^JeBSIUBicoJSDOkf0xo1pvC+yKnjlYXhJob3YxuiKoYH6guAz/OSu0Yr/Y+w8fY2r^JmvpnxCwaLbjmYG/ihbaXtiic6xXYjb+OQKfrRywvDQ28UKoLj7lZ0rZfBPPjqGvv^J/qFSiqKvgDua36DPiFy6UO4D2747V7uZoXtWJQEmSEJZOC1NEbyhztzIksHVcT8Z^JKVIHWPyVa69yvmKpIGgEqE92sEvgrKpbeH3xJEekHPkDpCtojjVGJ1Vm2/OrNitV^JMWha/HsUn6obKV7MYIgSIH2BQfs01araaHR54nKL1PmwHvTnYKo7BY3IKxFsDVq/^J/QQWyib6DNqYagd8+jz8tgG3m8/RX0ZO3V8wLgpPNXgXruBIdaqimwPYu6Msstuc^Jj9tPBWiX8XVhrrtoTg7bV2L9rlOdVY10amL4qfcFFjtlbce25vXRwr+DO2En/lqR^JDUngzYLwMTCCb5fEQPPIh/3/paYE+4T1eYQE5WoIO7OLaryzHXqWR1TfWEKAm2gx^JZvlf1Gtwlnuy+Qi8s7TG2/uGg6GqlS3DnL1ryzntYO+7J41qJw3u3Kiv+AhO23eZ^JgUhR5E9InJ4kPQ+g5TyB0l/nAIS4ztOXvAgXDOa0YnkJYlHEJry/UlRGCijyrDr+^Jlumbv8YtfhzX3Px3ufUYVxhW+utGUI24AVKpUf4FjlX7ClDulSGVdE8AxHNZHK00^JpjAPL1SigMdn7Y8xym+NG7XIcHadTc0HW4U45wAZBICwE5Q60vzCbNIEqy8luyAJ^JaTMiI9W9rL0Pf7mkoSZhmfdzdQ2+CV+m0I4EapkS2kBUGOUdyVm51lmsFLGsAtnb^JRlKhBOnSB9tnLy7u2bXqju6c+BW97DLB1mApXC149/KBbsVpxxC8B/WKmDMnFwgk^JGuRP7bMBxZTamnBUFoFazFFUf/JvhG/8ZRn3bn9zcpBVmK65p/6aua5oIEF8lHQJ^Jj69dCO2JnECvpuuLmPzX0KITgnsXec0jKMbkujHsSB1q0WzO4roQCP33d7QhWbb9^J93xNd8S7vWs+jENQ/d+Sab4bIsEAZzjzRhBd6Z2Y+2e0lL4225SjTlQV0rTK4hbI^JV26RP3ooaA2cl0dMZ4n7L+kMKh83wRvHxV0oD218YzsVZZk7azUr+6L4KvzOU6Xf^JFQDP05ykX6k3Ix7Xg+aoIUvThAU0hyYxn2aEcZtQqVtJ45FYym9/8mdeBbNlmI++^JZK1fC7vylUhO9comEAUWcAeIETXwnb2O0syp6ArLVPuTPF07OdpqY9g5ooje/vGA^JCOCF3OCghSfV4HmgHaMDbxV040bMyUrFwX+33QKg6H8tZr9H3FHoKSrn6D8viKyf^Jw1iA2H8fb8HSN2hHjlUFJZEvaYTnUWWmXTzwcNsAJGwpdilBZCB+kfTpHuc0j7TS^JbzbMh7eZRLBrPH/B8PGv3s+vG02KwKrBPRN8saDMRFlp3Y+dfYlycpVLkbYTiP0D^JdadaY/6GaX4dYrGNhHS0uZwcwUjSmaOniwgmEPyjwPmAN9DdNYR/d9cd3eRYEXor^JyJYEPiSt3OLT3Qn5+L9+dKnIaJs0CqjItKgoNAvmEACxdGui2T1G+TOVSupPlHwX^JYJaiMo99b0u5WfPefYXPLAO6yBXu1lKvLSPbyyd8epZY2i5Y+/arhEp99fJPt8Ja^Jfy9Kl1XWi2nDaDFhuV+26wGK/hasMdgkl4MpFR1SaZOTIHnjOI8j7DqqdZ3yE3xz^Jzvh+NYohCU4K6WD7nkkQydb3ddMHd12fdJvI0YRw/QmsRQ5N3BLMVhPYFhHuVHan^JHeyfnIKzmS9uaDiuSkx7c7or7fyLP93uDjs1w7DoMn1/oWWV8A+k/wNcw+TCybkd^J9ZZbX/5hBy+jdc4UuRt57B2cm/HWuVaM3zZngz9k01iy8R3xik+D8Kd4bfpO3Rfx^J/u3qB973X46IX9YkRi0nfRM+PGYvC62FaUArk7h5vxEuSuG6hDF2AtIfdsWSQv31^J5hL6I9IxT5vbhRK+h15V3rdTDcN6MlF6mwN72cLPsylxfR9jpUVW2ab+gL6/v7rn^JHgZeyYV9CpIBEelHIY9TMqCY8GeGQno8K9vvwugx2ky1yGoZ8fCrLZy4umRd9wGE^JIoqdDAlWqIpvqf675V4Db5s/y7uv5p7CMNCWh/APdpWvzlWQ2XgVQtecl6sAhB6J^Jh9XbFWh4dVAC/ftbzd1nxuqDNUBDZYR6WniWIuPZIDsv+mcxrqA/8uSDAKfCT+VQ^JZIy9aMLfli23hZOlayfOTzBrl4/cDgnw3fWMVB8WZEdj2GQqeGZu3upC4QdR0c2Y^JKDdkAh2ekhJEiNA9L2DnZXtxXcgKA4x6Ok1AXY2SIRpTN4UED2CWnqqA54Cg0s66^JpIWUZZrK2t+wKumRXkszD8+s0tpgqjCCjHLagzIB2jphatxseHVe/RE+Sp+Ooo6t^JKqJn7fFIL81GA4SB/qwinU0jV2pyW9naCTO7clu1d4BTAE2Kz9q54zp37BlKmcTF^JloBrygICa/NvtyinA4nqkGJKO75Q15eDEXhzW8PUMxZkNJzqUHY8QkifKkVmYp2k^J4VSZ7VObaui3sH8mc+uh0i2vlXNHJMOrt4taJ0SyWbryPXP3wxDxzo2gbyTlqPDF^J2JBSRPIGTTf4WeeN51j7ZrQK8zYktg1urhtBYABHdeSz3aIoE2qTR9U5lvNB/bCN^JwPN5Elb/grlAyD/d4k+d8Vy9GgKNq1nqtjI2uGqf4x69CSn7HH2Bfe6MUx0L70da^Jd07M4tkaFBMbOwen7rnP2T3nqmrikYWyyS1GXjW9Ts6UPF3O4UpL0ZaUsTwv2+F5^Jzc/IFns7Udyys8+sJnRg0EaFN/VnOk943VTWidbN6ezorOF5dBAPloXhcBaRs5jB^JeDta11oVC4PmOo55lwKMAMG8kyTps+tFFLJl+uXiYTj+pTayYPEk6d/zWp/wB/3S^J40VLs00fF+OeaguQ2bElfnXK9+HP0Hyusa77YpetVmIYAoOuySVcjsa5xS6MncIU^JEQdNnDhiN/MWKikaLzcaF7KTKtkaYzrs/Wx29n/eb+53xKKU5qwPCFQuGzwbcUST^JbbnMA0ucEYthm2//t2drRFQJc5vdUjr5wyjrAH00c1OLovXW+jsdvpQjYOBwG/OI^JlWOdt+aDoxwdz4mn9QXG3+9UjDpIYPj4XehovH++hWJj0fdiySNKaacOoNwVV6ty^Jl6MkknvVhYIPG5l29n2voBSYzMoBZmOvU1D9wG7y4rwPDC9K+5cIGk1Q7U3FzvBG^J2oOBgdrBa8VXwAZkC+PIHhgmEqRHvzAIhRLfzgNTwSXeeu8gHck8CD+lBWkayV1g^JKvsGRgQ8h89RRHo6Ky0L8XoCsOsEyb+m4Zsq6YeCceNV7DFCFw+GEzVvtLSYtFtr^JF08tKhpYZOEMSqPv9SUbcL/HtVl1+FRnTUe5UxDXrwVX16RvPaqFs15nJfFLqgDm^J3WFjmi7W4aIgSQUBUlEue34hTWPRpauluaAuKStu3xNoNm9aKfo24cPJsQdCIiMD^JuRL3FqyjNfZKo82X/OKqt0EYfK3w9ys7t0ewAO59Bm4eokdARepljfbHXy4X8+/O^JF5aguc6m74jgVoEPxdffprU4T7vXwVO8k3FmZ7+JrBsPRI4hTwVqRevgIoPYBpxe^JngSfxNNFscFYjbRIPcMlauvnwkrVnD48VZnsOpNszl/FbCNfolM19WCdLHCiIUPB^JiJA+ozEbiijt92F4hv+ALQksEzrgbrr48t1/YOK3WvZJrFNhKoQKpQ3JTWMnMoke^JOHel5uQez/iUSwNLxlnFaBRptfUgugdb6i5NkWxudWYAWJSoxHwQMUuE9NpTG3ha^JiFEPCIzX1FqXkZCnGyTdWc1WQwthefC3atUR2dSR0MeGhAbVpDputwB6gJB263mX^Jh0J9Gd1G8/6g93fM7AXHC3K67phaLmLHG2NkNH6Q2HnOw7BkRuhYuWhG9/v15ih1^JuhoMnEHvgnDke4C5FxpV6A3T0XaGJjfqre/4MAHELmXfSd+RlF5FR7ZnWNjPTL9l^JlnsqEXQ+DpsHFWfo0SU5tC5PBM//ZwozP45FOVxKEjk4z59tGZwg7wgJEZfEzjTb^JQotqYrFWpa8LwueJPbsPnFTOGDtIVPzg12Gg0s5mNTXv3LgyZjJ5Ot1aQUOeoMEd^JaYK3G9a92Hq/6ugfvlqtOe7uV2NJp3K6Kav5RI7di1K+4Hl6T6ohq0BEo1JU+BHT^JyWPSVqkrNIAYA/ShG3ipO8cV6MUcnlRzBgYvn7/fWpeAbDkXDNxYxmfmTIgUwMm1^JzUgAj8KNEjGc7NRIkIhD/taYl/H0dbBbGdlhzGQMu9a1xQ2w+3wQBo2cLywAAf+A^JsbQvkP3L7+8DJ8Ai76GSuA238Coj/k2WFLvGJCG53kNxydjZT9Q9NhP0/bwUObaI^J0Hw2mXfxhBn6+qNJN+hwktzS4zrgq8nbdLtPRvBYYbubYASw1ZUWfJy6GxmiT3OA^JOuGA4C+siVqQRpTAW4AyzNEwNgjw5Apxq790EwMC8lZhdmSbAdRvI4LUgZFKU7sq^JOGKF46fAxsgVcJI7JgpRB4LX7jOrSiqHj6BptA1fHndIrQ/6XTOzsC3JTnKKIXBC^JXAp3HO9zAas7llLvSRDmVR0NfBpjNwCeIFxp4bY3eYHKxruGylwelY87G73UoTmp^J7BpfYuOtdFXi+MfWzSd4hQsoxBiLbDbXL+OSMI2aegXGtMJMGt7NL0QYqqO0d+z+^JnvezoFA7xnqZou/M3Zjo/VABy/m1HBMdTU5g6G4WD+8aw+TDfvPK+Op4Lb7MuyxE^JSmPBxPaHEQYmCKMzOwGQEI/AH0mM5UTOLpfurfQ/FaQthUuPfL1sraZBV1uxWWZ+^JunTkttIUWlX1CF7AqN6o92QF4MpjZwn6dtU/WLmDm/j64CjlRifNP3hPL7xDXR4O^JfFU3aFO1AjB0Md0d4OnbtiBHd3xVtg9o2noglEdSEoboBz8ikZa1kq5vu3kgqAVQ^Jz/w+zhw49o9GDo583jLECbxOIrfMgxnv2RND/Etoc9XOY3U6d2C55GTzN5CwvG8y^JmObnT77IkD8PHKb7B4+zO40GWfsGdc1JwJ8VuetrEZKqxpyf3TtgPQ8gWkJt7zt5^JWjoZhrHI7opFo3uFDC23dOmVBPQkXzC8IyYcRT1B/Wh7um3X+ZXdUTyq1e60sC8A^JRNRy+Nd2OQkEH5BiCmunb+kvfdx739i5dLQWrIgvDFJPmfbUhyuyqDboxTMedNpn^JbebTEbrFJFxCwOLREtTWMaXorDnEd9X0YrxkkljwYUweiZIgOZu7QALj4G0an8EZ^J+i88NMdD+KONWySuZL8UGpuWMqOG5qpt8oMAXuNZgjnGu+dPmQ7PiTIftkIldgA0^J/mzOt31RkN/+YuL9sEHXfZPCATwqRJoWfTHYKRLjyvnKK8UclTAiwkgehUD8dpJK^J/f0kzIA0AaNotwMIY2S8h+2wAsDpTUmg+47izIoAiylX2Ek0kMLY/cMQp/pZJII+^JnSqLkbbJC1iJTkzzkA4Sq9BEwYHX+AQACfR1XSi5fQ1cwFl4oIftsFhUnrW1yIkD^JkqnvkFP21puNq/Cb8uKJD+qRTpePrke3+Q5cndY0nPI9S2PABdmPOPABA380EjtN^Jva499Dxgcuozj7C42DVdthSiedF1V/MZgWTG6CCdDZijf0/dEkxpMFDrdCm9gr9/^J0BzznU1hXXrug0xIlZ81W935KgcSwzT62vp1EAT5L8vZN57Oog8VTVTmTPKnOSo4^J/1YPJnTYkvBoW1YeHBSvJaik6g9lqtqUsb+aup5QoY2SKM/WMZIpHz0OUsidZywA^JX2GgunrW8R2jgYqi7icCt6soC0a/M1AeT2g6zAaGD8TI5gRZWmrGvqKZXFK1zkP1^J+1ri6w2Bothzg8tz1eG7Uuyu/jHP0ENz4DlfTawIRot55VHPh4dNiv2akdza0LUs^J7rdoa+ZIevf2jyvC7YZP46i3V4OHhdh8u8DLJFTpK4yzSSaFNpFJ0hurpyqwAtf5^JoB70MY69lVZwhuCn7249QbGZ7vc9aCBtWP9sx2kUHQG9l/WQ5VSrrsfcJqnw9AzY^JePk/Yv0O0LFIuHL8ZjkSNVfvaC59Fi7cRqJ7PKZDbFQz3cMfyaGs9NBE73EDv7lF^JOCCh8G/Ocg3EWzBkin6mnrvOy1hu4EDD7yQqeVS0+xHQPZICr9X0SKGXXUyvn4eL^J89+8cIACBlOecMs3pnrhlLIla790gySCmCybrwXtAfN1byomJL2wsQqcLeXiLAwJ^JgGXKTjJZXgRTq8qFjrqw1JBuqYo/BMuOAO8P175zbX97Nn5uy4YE15aBG/5GsDhn^JhhVhncMJUyJNyhj//PSDPvXWbDWD5TG58PZih6mhadE3Do6eRPfVVx8OlOsfLiHg^JHa7+s1aX/bX9+Ibng4khoSjNGYIIg3dmF+EZ0MUEfxmV2OxItlPCcxvK7850S3C5^JcOuJHqzzbJdz7J1/hAFs8z0w2ndIFNdf23jWZ/BsfaHhyjel2KEnrTpSVqSiOi3Z^JYxIiHk2EH+0VAlcmtbfFSreDi+1E+Mi1O3DMUoNZJpiPwJxGjPaBdM6yRACrByy8^JY4YRH1VBJ6zZcIiKjjP08csRizu1nfKOsalhmaMpPGCvPkDvKFIp2BJxDcpMU/Cc^JyyDmV57jx7BH3txuyIw/TQIDuQ/As0+37GW1t+n0hyuaG3LjjZRPM1oqR0svvmU2^JiuXx2lkuwcKcrvKcXYiueacKdkizP3SirDTsDsTejrbGLkIoFWg11vNl/AZ7KW8F^J3s6EwVAdSaVTn6kb9TE0045O1bTuu8DHbDbGJnA7u+4am7ToX0iSo1yaOOIEzhA7^JYvVoTDFsfKSdLtHNEO/wlXoYHBuOAQw093Z+2GAyWfq5y/qT7vh5FYL2WbF6g8xc^Jta6ebB9Rqno1xC2BTwgwJ6VPzpFS3r8ArWdelq/0GCHIj/6x/2AfXQX+mvbE77gE^JMEHB2Qo+tZQCIqAnNNuaAjbBHuvLSy3c+sNYnvJoyzQ5yK8+gdtbJethaaWXk7jI^J4PU0t1LamlEWGZMKISK3zn8pfQAdh+ozYprnaQsqYjSBUsb3SAsI1CgVMSd/p4iW^JZdeA2vt35dsm3JaJNIrbk82AP12PH1DQW84zEee4+ljsUmnNnocNAyTqfkjTdRCZ^Jm5m2kTijKb+72KH5qnMRIMJHOZJ1etLLWGxGPwQ6ZcIW1qSkisv3HjjTkKGaHiyQ^JCBViKUVCZ70DAtEhdxnt4We4AqkHLF/HQKkKixTiQyYmmuHGr0NqOaNxcG05tPZ+^J4mBbI97OnVszlYi3XYIvd2gll/+KCrun3yURvzVML6RrnqPwnGeLyGoFpqvvUSji^JVi0S6tgNKEA1644bmTuWP9zszpKVNRH8mbgVMpxNN+830CbqiBZosE4TuP36D2Ug^JLq265sflRY62rzGEI/EsJ2L47t7waTIQk3sxIzR70mZlJqchH6VhnfTk6S2Xgrv9^J6cMZxvVtAeSCsXAi5J9wgdso8z07jgRvzPG5Lzx6ILVEKE2sJQdxaleHFAjY/fXG^Jdb4vLk3NELU4zh4iNgB77XshiNeeCoYp3a9TipOrHCPj5txwICaUeaE42auHkdjb^JQSBABJwLOd+bXZWuQpFqZ8j9OjXC6q1HZi13VVreLhsD2yiUjhQn00V3d8gEfPFv^J045cUboZlWsU110UV/7OLDke2Vvd/gTp9EAb62EPAR7W8kRA2gfYbxoa0LqB1zK4^J9H6Dbir4dd7WOx+CfQD/LbRVWUBgL8E5Kt3WhAFkb1Rtnzs0fVAijk/bauFIadLT^J5wKK6nfjv73wYAKbwkw6+Rmo5Ki86YjF5VgFbjtYwcUvN9xabNl7xh9rtdtyq/4b^JkhzC/jwyg5pvg7p8v/q8Mbm7wY9Xv0fZxYaLin+tcq150yNycwmxoO4oyEXLx8NK^JTrmZKIGbJ1MiFmh/AuB1kMoZbDy37kvOs0yJjl0fA2SuSlulkFzWekmuLnVfbZJF^JvhLRPdpM5OY55IY62ICkRAnCX+j9/i5jx0BSSfmB4Yhh63szrF6slKZfITssSAkp^JhdaAyfAhBTu/APBF2GgEh4BiL2fpK8a4LFZtSZWIqwHa4bmWjyjRJBuvK7GjbLeg^JDnCuPPdNOwfPeuhW2B8h7FM8rEhwtJIysP62lpNuIeD876yB2uCsYYvnIx6Sx3qX^JhX+2xkF5p5vh6sM8WnnZqbVN9lI/5ru/sghlopPt/mUMuYcR73ja9odPtYCYbZTa^JK/oCCS3lu6BFmyCsHOUgn7Dn8mGsorOdzfa/W6/Es4AgtqPS3VynrTgt/nKUULi0^Jez0yIkIOHqYkl6DrmJIOXrwwxqMgSrTe0vvrOdTifQaDF/MTgfHp1+xuEpi3Xgzz^J8gKRAPIgMJkm44YPlBRRfYTzrFYPGJxeMe4CnL6NgcN6TCE7Y0aOvpbgBw6/JZd9^JqC1sLRbKuUkkRzzN0T6LcHX95RCcL/9Lp1RKqaoQnX0wZhskLkGz3/L9rDDtLeAM^JhTYExb6VAciL9a9oeOTJDXjJ2MQGjUVAHjouLLtFJLdmrqpc+tUFB2L5IW/ZgP1u^JHcmlIa2m5lxxcFHdYRo8FVtM8avDhunvmtMaYL0LBP1HmHr8xl42ICSqASRPUw8t^JE0siS+GwIdM/F2X2NH0sz/leTvVVl2iD7suRUHVk0vHa5+lypZcCSQ9qvp7mXIfs^JmOfwRNn8VT4UHRi1gjsEwXEUyLXPxOAq7MlO714gWtZYWiXJXnDVPL88Tai1eMz3^JVrzkpFUTW5DtNiRRM4DbZMtjcv0J+tunLbrHvVRaVYKnuwZlFL+6X+Cr0BzmkOoL^Jxm+8Gf8+Iih859+rRj8/T7lPV+S87zQAUcXXTiEvJrl86DJ9Kl +file_chunk, 752, 380370192, GsvqfXiJ4np0khHUmapJNPmJQKa0luEG6FpCzgp0Dyl47QbUHksinrhMu^Jo8584ANcgv0sVUAruYbHZKqWHF1iaF33J5moGutRzOir5TpCwsYtUJTItLPqAigi^JUZIpKxPbO1Qu7ogRR+m96RRQWPGMM0gtauwU8a4i920bBrETqumRuEBs11GgfVBH^JZAc44gk8Dg0YmuX2XnxxWHxqQkVbpHoDLGzeFh/3DkQ9xmAFWktrZHoefkUFgJ68^J1JG8ovCJUheKpSkhI7xcm/OLvfXpVZMatajQGo+4pCA28fQ7SlO0NJuQQUB1Dl9H^JYKuqg6sXuXE3n2BtmQW3LMUG4EIA7bplb0Njb2sCxh/XjApgMVQXzzAmhwuz4o4k^JiaecwnEheh8CLnv8JWMshGw1zDgidP5HbJ3siVD1QhFGmMvkX/ZM7bo7zMZfpRbE^JMdVIb5jJBGUXl1lCol3qbMnSoHNhOo7doGEFhTuVvXK8lP/bmlssoH8aGc52bjws^JYZXn2kVUhUV7d4TJzPhByjKFHg1mY4WZVwRUG2TbgOiy74z5brEhU5/he3helhy8^JqXMSQKGZlMqbHByHDEjBYpR2PqebUuuDPNpkmZ2nNG4NAVOa0gvDcrocMsCEbW8F^JXp2Bmrxj4idyuqruml/tmhYEm1JSPqnAtJCvldK/Ksu7WSMXDYZSitG+2Q4n0L6V^Ju62Pt8j5vMU0RRCbqq3ETqSUEqasL96nHQys/ppzaraC +file_chunk, 752, 380763408, gXdxRZzzH8TAPLeCpKo4lkFco7^JVvkx0JG2M4OVAYmaExT9D1KAHw2PxHnIgNUBq1jHnyj9VEq9r4q3ImdsoysEswws^JNzUDy0dboVl7ZetTP6iOLaeghpKUezHDfHFdgQJK0M7l0GTps9dKqumA6vb8zElx^Jf7tgGXKbPgGXirMekktHzJmb0egVOxwdxRihS5KggKG4u8uNGqq/0vcIZuQCBvVZ^JDCUdJG8s0L9aqifuzQ+3y/4v0l+qQ3daY20plf/KWhbp9T3QBCiutmbMSnIQoK/H^JZ7yqa1h2w1aSgSOStv2tWtCcjjgmBI8acLZ/D6/LZAgF9ZdEfSnK9+39yw9vHg9W^J2IpsFzmtD+CyQ1eVrarHiGL0cDd9kKPE45czXjT96cjk40+SgN/08efxvRvOZpV4^JMvW3fHpSFS8UQecdE+NKyPqf9zEMd/8UBwzKD6PQHJ8HpCLIFdy+wsbwU4+yRJBC^JTdEOlDT8j+laAmErlQw8Mgf5KcPx1hBIqecPaZqfpz5r6LmCXYbZQVW8E318CJfF^J7vGlrZLQh/x6/0oOICTUqd/CaPGhXDrrS2MRGbCEG5N/n/qIQUyyBJoXbPp1AAwG^J8OlwvOcAQWh0AJoXwI4bFF3lqIsBvLwVOL20uRIqsAfmxle6nfwSKAT8FDnqyAng^JBsPh4X3wUmOKuqG9cZhc5544WG1Ec8WRKmEB8ru24k3Lw0GsFPYNLpmbrYPofVlh^JXbH69HCe18 +file_chunk, 752, 2293234960, bE5SAPMll^Jaib84k6IRyHiKCbCiaAZVHGn7mK06uxYUbD7bZSfWLRVOrJpAwF7KCprFfMglIo0^JwCSYXGRoYX87FbYLtOCxuc/rFQE3JjNQMmNbTjxQv69xmpCQ6VWs8ePj3n9hDuAC^JBLq/iJ2h6hKeLUfcpblaJ4+2hHO+Bfr1PX6juuATkCex1QMCAr0ykNuXrirTvGm9^JHFjQyOKV1Mk5srxRXf0o9CZDnw0h02cDV1Zm/MzpnmA1uRy4mNBGXmR4tXn6Jype^JCwrONyUP6jDaRQDeqLnniEKnZrPvu+33rAdFK+1TRzr//gnudo2nj6ehzw5GavxS^JOYOjpXTQKo3sXtDuO0XKtGlQMN7cdV95tkXEpyatfdjFs57BBXyih/w50WfNRlJ9^JvDcC21ht9AuYP/7/N1sSAZ8O5icTEqiLox1gm/s7CJR38nN695+0aGRrI2zdnZJD^JffR7ha8uqFsfJbJSIBrqHXsSleF8hjqlVTXyGpd/yo96KsYk1qKsIdgkMVT+cMuf^JjFwxhTW+BH8s+K00eNzpjIUzJY8fUOusUYbWNlvRHZVzs1zKUzJiWNmKSEQkAVnx^Jp+wWj5yQKPJyIwJUR2DcGzkXES8udDbfstiPqRHeAUcm3otjWQzn78jdQ/trYq03^Jh/yu+wuWsMazmSoDY5kEXCYLovRX8zBfPsT0/yx4Jk9eTdo1AY10E7mMFOufZ31O^JNSZ5clGw/3oyPNw0Dthl6RJGRMl +file_chunk, 752, 2338716944, rKkq7+/L7WcTv1pXM2kK^JARYWqoQyfEpftTMC+UdQgVQxklO0zOYQwIOF3I50JNSycpqO6QWEVCr/yNarcSQC^JALVtH/fJKp76r/825GduosjDFDlYyohREwQqqvYlnXszy6DeIVN3Fpb+ChkwvNmw^J1XVj74VT8QQH2g1fbwQsjL4QOw/xLqgZtq/3SiDLvOsnrpvuN5oQcUdV+1g12I1N^JJCznvVYVUTBnNWV1wNFecvuBxGYRETJE1aRHFimjFAezAVSW+FcwwHhcXY/8mpNN^JJieshkOjYKeUjhla2fDXH7OY1aS0T/bqBUqkdVTjkm0C3E6NlUGUA5t31I4jqEb5^JbNwrKpLJqCjpr/uRs+e9ef1mais77rMwxMxu3zOgI0+Wl7oEt4HXPMbLw7FlXByH^JPm3D3f0Vm/rsfABU7nPH8EOfR0Ad5WY4Ul+K8HGgFL5EpWgagrAxIm8ZMba0G37O^Jyt0CBAy0FJvTMCaIuFlL1VshcatltJqKgVoClur2gn8mnsMEKMsgLNE57G/v75aa^JK2G1EuFFg8F27Ry8WPFJhdnMBno5NIlBlp4a+GNnoyYypvSiyCH6ep0mmHCkInjI^Js25AU8PJzVK5fgJgZITJcS2ID4bQCFy4mVn4MtlPAQOGbZ4f1mNHWKXEj/arz9jx^J2LnF9I9OfP2SIUNuGr6EnZ1JO1ycPFh5Pmd7Cpl1MO9APB2RpwZ7FwAuwfNzRtHv^Jsgutwr6ceMsddeT9 +file_chunk, 752, 4260756752, 4Qr21M3p5vrxpuLqal1FrU4X8z1+r05kDvqcs1RzecdzoBp/FCMU^JykfOgs1BNZU6UypSW2vwOxaQFJSTb90OAdX6hpyTSRT+k1RaGwGdWgn7OdFgdizP^J4Qo6W9abCfi+6BnzHkxxSFTQfd9AFWZ1LlPw5+NjUXfxdi/jGLtDIopnKAE8LshA^J108MLfjjWwlcqs4v1XJHGfjCaauVsrRdes8uhXfiCZgUL0KOKvwHvBy2TKLDb3ZY^JAeJxEBZlgadEjxXjyQZ4BcvU1Gwa2TaIfKsM/2mCTiCIqBo3Mw5tVHkDvEBGKUdS^JvY8E9bpKp26Y2ejYdVk8JSt58wDHzNBeO7ocmzBn3s2fQNbiwX3I+eeJjkogqKTa^JjQSAGi+bUGKWE9dZyDkMZd7NnvLhxO2gEoRlYYjVuDDeDbXvBtLHDa6puLcO1p0Q^JHIkzRmtMTV5SVPhXjQCJyps/bp5v/HzViCLRfXiL0+nDDVesaVbhko71aICGI9Pn^JsvSR7E4qvDdzOppjmWKkau8QcuhLKlzUpyEI1SNAGzrSqL2OuHqdUK5ypuL8RZmm^JXGGDmJ27yMYNjgr3aTJ13eJLH/MQvLAIBys7GKM9BZ0UJW8W4KpbDFRRJieo/62U^JWtkGoNw6dRiCdkuHkWRs40aKc1yhDaoMxY9BHpMtUuxid9Qu9MCiAs33JHLzc+so^JBeFtAtKFW1VSSe31oO9fUfgGucj9BP3QpaqFA0t30TazwxUj3 +file_chunk, 2896, 4303090112, yZg/LJ/GpmwgXe+ESFWIDa^JxR4TdIMTekg4qqCL5PpNJ6DHfkkdsjsQ9zqkWNtrc/GpqBPClN8IwD4qThUGd+tI^JTe38v0hZWuuNnOjY9eJO747wIiPqy15oBYpstGeIdESgUFr9/xg82fGjalkY2ZVQ^JJAlH0xNX+TF5QIn9BUMnxn6OCA0DkQYqybz2eq82jB7ZEnGLdDvB8WeaQIjxBuVx^JDAiCwzjC2jpO+wNYCorVym4VFti4AgGYghyLmyAicit9NqPTMsaD2BbRpb/qHg0P^JdX53dFZe0qlqsrA15n3KCuLiw5YXEFUmUQuAN0dAOqlzOTOPpNmJakHF3TqIXvw6^JV/qERQeuiNPwnBZWrZvpTjO50VatjcUizhJRwTiQjbQ7+mqgHxiEa9abpzqlTN2I^JW/uUssi0jaVeFdL3MHZYHltusyTx0F4iH+KGJ1n7YRefPAI5klNZu3XmTQsQafkF^J1DMVbqcJT+aLdlz2hWMy1R0BfV2XMrO2/XhG2nOScnRzS8Z7EmAgqZmzFfF+nqyP^J9UCd39Si6aUrss3N0oCJ/44F3T55uSHYf2LCgoaaiR5IML5tk9mHVRyTile5iF3P^JNPwMnlSeka31pzsqLRiWIAvKqk5yZJ1v290/Aff0SSIxKggtVMBq3YmJeRb6LrkJ^JjkYC41zT+lvvvMRBJCFOOXBgesIBHq7pOKBKPY/xAcN/e+AQqHLlY/OGMT6+GK9v^JGXN4TvdRLBYHZQqyk2ITYWD5iQqweeZ2UmjB3Is3lDKtnlO6qbWvvYmYPoXDrNI5^JhRX0gaiVC5LyZZ9NheeAgb5ZTqYUcvNCxM7BFV7gJMFXc8gT7A0FG3YbkV9Y4D7v^J3NduhJG8kgS814/l3Il9K3jc12uv8V25orXa4lDXTbTu8WanSYUkg4cLjqfKD5Vh^Jly0ZTpYeNx1NdO8FoSGJhqI0BC/p2NyjzmTh3mrGk6tnfHuqXAMH5tIt/EC10MmP^JE2WTu0XrNk7I9bWBRRNWx+ysP1CJUd5GbYOcQpFHBfG+9ApIf3LjxSLU00/b7Ui2^Jz/92JI8T6X4TdKxA7DY10IJg6KJBsUAUJ9Co6Fxr9+9OIo0bdj1IcD5+w/qB7xzJ^JNC3dgXc86uEDpvICZS2vIeCZTrc9vgxBxpftsdVNn1nDYlalXZeNsAmDiy3QJ/wO^JPS3Li40x0KtDWbxMzgflfzuyMZQBFSNeQ7CXFh9mJMJQkuAtHN+yAEqJJKaYV1bt^JJM2jAeKb64mN31lIzTnkJEGWcvLNS0uiZKJQrm0lqsentMitzc/+U0gSxzsfbqmW^J187RzZAsNlfWnLN7miAPsdxas2JGGrmHzjaUkL7U+YJdAToYlxjMTnZgztt9LJxA^JSprIv68hyNVF+4+fpL7QER9EOmgQOIxjlxCx75SDd5g3CWJkVbXl8uU6G+j02j+Y^JcOXNTTwX2ptbc/79Kw9iDMV9YkAZtP8BD0Any1Fqh/IMx4QcMXEx46yDV2ji7umH^J1SO686Lv9zGXYb+ApuY6PVuICTJrWLIZBE48otTKBXTJ27wGiEf28Z7bh74P06Qv^JXMTUryBMDg9JrcCGTvelIZO+DbMMMN72Mh/lXBAOLIkfh9WvgqyMIH1kfg0H3AwN^JB9b689RpbK0N+xhfV/aIqGp3a1KbXqPA/h85vUI1aLXPreBN9gyTKe5K0HXw3Edo^JqMcB6m//PN72r6epmEMgdthZs5GtNcQBx2GbOonY1sot6ZA41GR4hfl+EJPc81uY^J55uCcANhvaaIl+V7GCjV414dNq89TzNFHF1sG3ifM5ePRhFHVnsE8HgoE3hsMhqH^J87vMDghqNZi7+tGPNjZvZGVtB+RL8ltGhUSuoE9OjU9S96T14TZT8ksIo2jb6+Tq^J6Vo3Y3vKc6krHH93OKiXN0hwqPupBD6xo/23Ivnk1qu4xAZ2fnR1Ob0BKcPCrNdi^JREI++RJzxugNvbGOf2LIdoI/2yChB5i4tg3qYRRRagUpNohIxW5eJy5ugiCwOH6d^JuPmvLXUzs3J0HWdCVpmgURIP4omxgUkLYeJNp4CmeTAUr6uVrqzRCDYPOYrCT4tB^JYL6uyxhmOfwL5/YuVtsCcKjX8nGvOIHdtiMolPpeH8qdv0zp9kY+h8eTE/WGh5HF^JA4VLUCH5d8qok38Q2Xvtiji0QrKr4j+P5Vhp8YbKLwFEqs3+NvA1iEx/RQhTvPO+^JHCdnaCc0vIaAp3jR88OrMDhHyKePPMk6shiWiFM4atdQesswq11pHaUrUoATZGm+^JG4IsH5+DZVk+ztcDnA2+f1+FKDFHloA7VWMiuccer4ZHFqaB1WGpTOMTBF0xhBYo^JmhRBLM+O3SJ3+I3FwbmE4mPnh8PMalte/qm9IFtDIhVdoo5+lS4tarJTPwazW+cs^JAIxETVWHanH/QOtyEdrnufA+kcj9DLRA0IUQLySOYCGQ3ZZsHyyEDV/9IWOjpARW^JDObwlGFQk2mWcH4/CdOl0ZQajrk2hWbwDuFx+RVy84JapHNIAFgH48u+bn+hgf3V^JVX1bUYtRpwrBEEBwD9rQJ6iMmeqg2B/Ih9RxPBq3wyvbhzk/VVCaUq3c+XLz+6B/^JwaUQeYEQ32U8XkaKbWsXxrcKZvZ70oYLGU1+mHLV/Lc/vwch4nAJmtRYRrZ8hXgx^J7CRciM9baxlkZ8zAaRXcGW2Gbl8m//oHERz8/8j7YpbkY3Y0qfeIqNoQyHieLPc+^JWwUfKskpxIgL7MhKlDs1fmJe6X6o3KW11JZqldPwKL6WGK5P4OS2fULClB9MD605^JNpjTRR0NBoNpKKr6UApGAqwfZmc+7oGZHVBw41tiCKuAavQydcOtOg7Xj84i26J1^JBppraxJIvxoJ3 +file_chunk, 752, 4675468560, +DcPcn4qO^JffnlMfb0kLM2x5RyTcNksyV29GDPpFDXWpehoJ56Wt8CMltAlRzSEEPAjWTISMvB^JgYHW2wKs9VHgQ4x2pxmnLTGmMKS49QFadEaILpCb7Vbi+EnWeDwitcBjWI2GrSMq^JYvex9t0vSEt1BrebNcumhwZ4fEjJ8+aci+ZW/r6ZVd7NMrSKMYpMTp1YxTqbp4xJ^JoogVMhE9enlaPiI39lS6mcjK9PZoY2nxTAjxD+vmsFrToCFtxp0aMcJzLsbjhQ7E^JTJX+jYH9mwJiX+mjghmb1npCkjCCZkl04m2cQwYN6xtyXRniEQwpKNK5KCcbfIPb^JYXDXWKvy61KJQli/DtUjh9rhBLVGrn70CCuoCHxnYSlmq6Np3BBDt1PIGYxnhCak^J31ueqgP7CVDs+2/Hh7t4syiABQmA+Xvw3E+Zd9zPp+TjZoux7nPxFUx/rm3YFj5T^JvjlF+AruGVrzTVRmpKSY01wo1Nxv+pSpHg0GukvDnRqFHGSamlyxDrgx3orpqj3e^JD4Pg4voGdHLoVkTF+HXNjUZq8UGKz95B4Tvrpy5Ll9NwX3DD0wDG1RDJLw618W6U^JLThJEdnZcI6460SCpiqKhVXZo9vL0f2dYc+nswEjtgkFnUPQMvp2fK9XVEozQNiQ^JKAjg0dXTDJ2K4mSxc6UlXqLpYgomE9vX0dEq1i6b9IktZi9WckHR4nfV9F4Zd9bI^JgQbfa6KTmdmTrHM4+jtC5dZBDtV +file_chunk, 752, 4675730704, QvDDMBnvKD^Jf6O7XhaaVuulyRhTZPY7oJjJJXSEq/UK6XMmMRzTuPVwjK5hL8H8MvA9T5NPDNDN^J6awIHAtx9vRxa+fNXhfoE8roipZABMXCD510gRsS/yxmYat/2XSUVuwVcVfmLcUB^JGEIYmzbGTxPB9TfPccJVsKAD35jzeyTGsQjaW4B9I1cykWedRhvEd8AeL0O+vBCJ^JxUIWFEHet3dbQvasUZ30o0hMbgOiserhgO4tQ56U66e+Vl/VZUX+DpmxtTYTiVn5^JpVZfYQaoTUpzjAi9t8Iy3YJRwlQRgZHcnzmcDYNuvo4InrEHS1xZC6WcbenTIpSW^JkCGI7fhCLMabTW0FQ5AaSTFKXP7O9+nxdqdup0XJT8Twtuz8l6Mn4PkgqOn0A+bc^JQbtonpY5uIQwVCiAcYjpKAhGV+D1B3TDI5q2+Aj6WPQ9Bfi/pqfv3fBK5ihgY9LS^JW8jZEJCJduoEdsDyatqtSK3UOtftqPWVptW5JfuajYR3CPl84Xk4K1/cQxx5nAKi^JRGpvr0SVoJsS9HRSsoMlJB42Md0SVY0nwp3MO1gcOvKCA5SBI/KXIu0HQ3YpxT39^JV/sR/QjJZvj3u0hFehggRQVo25pQhq4RdCt2edeBwYoxmcJDhnOZD+nEYax8GRUu^JfrkPGVECNPqfzEePAZSv/8nW7ZHXz2+Cted/eRd0Y6qKO4KysL+kjDy2SX8ayrmA^JGlc8VABynj/sshoQi5/nz8nq7S +file_chunk, 1182, 5416665488, w7c/SP4xbc2p6HIRdJLpymJYcB8aLuc^JltM7qmD7UWqSwePzdNZkOYSY0/p2PiZikeQ4wn1fZW+24gY3Dr+oghOLSyl9RIc1^JgO1jwi/vDVySgarwx2QcGsqac32ow212k0FzWuHSsI5SY3e9Cxb279S79PH23+NC^Jrs3mJw0arb7RYD4ZYIrtnnrSHncN944NEmooPcHD/y10bpQFlvIDO5dPX5SC7ryP^JAHOAkFGnlbNJasU9jjuGbl5KfwAG+lm/WyBS3Qzs/jZKEm8xcba1t+4Tmy4HPfIH^JQycTiGZvabxgg34ZrUkRS/VRyNs5DYEl08BsJFJ4ErXqMxqIgqndmqmFCMWRbqm3^JW1SyJLU1BpESS7O/WtdE0h52qeMibJCuMmSLZ6Ji3ObkDuWnJyQOD6DiywAOd4MK^JRAKw6c/G6daqMCLAR8iYNbKv5vizBN0xq38jnjN78n2L+Q0cHigtBVYOb6g/tOod^JsLW0MZnv2UQ+GkD7mz0FgctEtk7LnEGwwFrOOHFTZWJ69Z670dS9KVIVNLVom+wU^JM2bjpD82xE3kLHtZ/VZ/p5UzZkhFZTMqHisrXqcE2hs3StrJj50t49UK+JeBmNSV^JH9rY7uihuKU1BQrSxgXtgW6HZ2st2VMNWsAFyXDtWAO6PrmSF6L+D811cXHCGZx2^JqmEH4/fh3Qyz4wWp+2qJgdfqlvIR9glBAvF/612vO7ig4LN3+g7LLaXy/gtujFki^J9Dnfq/yKN4IzQspkrRJEd/Zitw4HMnO40iTvk/qmfq0lvfCaJkLNlVqD19XJCPrt^J4gvtRiwNs9QfQht7lhUp/Wnt++6jJ7xrHqmqOMvd7oBX9H7VtZwAN/5tOhznLs9a^JqcBtokxx9c2lWCtgLnOHdNssIC5WcBfQqCnfCPrnq2A1QVGFoIkFin+RmvgdpC0x^JTJHK1ceRTrnNb6VBcmXnraSn5QZTIZ5F+SQ2rgqTNfofokJtEKAt8fUVrHZ81emS^Jf3sbH8UPfa9Xj0jmZmcjRRggrJ1yu0RsxUlxg5siQ2Fy5i3vAb0ZZ5ItWdIt8Jwt^JJFX0FWYGmphyo0Nwj/XP27NaqTwSOmo6xAfoyU7z/28U3k/qEbtLpn5xzVHk6Dny^JP0XGw4JttE7CmvwEi057FGGBu4pUYERfRNu7o+THlsQ=^J diff --git a/testing/btest/Baseline/scripts.base.protocols.modbus.exception_handling/weird.log b/testing/btest/Baseline/scripts.base.protocols.modbus.exception_handling/weird.log index 57fa59a1ef..d387f9682b 100644 --- a/testing/btest/Baseline/scripts.base.protocols.modbus.exception_handling/weird.log +++ b/testing/btest/Baseline/scripts.base.protocols.modbus.exception_handling/weird.log @@ -3,9 +3,11 @@ #empty_field (empty) #unset_field - #path weird -#open 2013-08-26-19-36-36 +#open 2014-04-07-19-37-09 #fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p name addl notice peer #types time string addr port addr port string string bool string 1153491909.414066 - - - - - truncated_IP - F bro 1153491912.529443 CXWv6p3arKYeMETxOg 192.168.66.235 2582 166.161.16.230 502 binpac exception: out_of_bound: WriteSingleRegisterRequest: 4 > 0 - F bro -#close 2013-08-26-19-36-36 +1153491920.661039 CXWv6p3arKYeMETxOg 192.168.66.235 2582 166.161.16.230 502 TCP_ack_underflow_or_misorder - F bro +1153491929.715910 CXWv6p3arKYeMETxOg 192.168.66.235 2582 166.161.16.230 502 TCP_seq_underflow_or_misorder - F bro +#close 2014-04-07-19-37-09 diff --git a/testing/btest/Traces/ftp/bigtransfer.pcap b/testing/btest/Traces/ftp/bigtransfer.pcap new file mode 100644 index 0000000000..f08f051c53 Binary files /dev/null and b/testing/btest/Traces/ftp/bigtransfer.pcap differ diff --git a/testing/btest/core/tcp/large-file-reassembly.bro b/testing/btest/core/tcp/large-file-reassembly.bro new file mode 100644 index 0000000000..655d030d96 --- /dev/null +++ b/testing/btest/core/tcp/large-file-reassembly.bro @@ -0,0 +1,22 @@ +# @TEST-EXEC: bro -r $TRACES/ftp/bigtransfer.pcap %INPUT >out +# @TEST-EXEC: btest-diff out +# @TEST-EXEC: btest-diff files.log +# @TEST-EXEC: btest-diff conn.log + +# The pcap has been truncated on purpose, so there's going to be large +# gaps that are there by design and shouldn't trigger the "skip +# deliveries" code paths because this test still needs to know about the +# payloads being delivered around critical boundaries (e.g. 32-bit TCP +# sequence wraparound and 32-bit data offsets). +redef tcp_excessive_data_without_further_acks=0; + +event file_chunk(f: fa_file, data: string, off: count) + { + print "file_chunk", |data|, off, data; + } + +event file_new(f: fa_file) + { + Files::add_analyzer(f, Files::ANALYZER_DATA_EVENT, + [$chunk_event=file_chunk]); + }