LCOV - code coverage report
Current view: top level - src - TCP.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 577 952 60.6 %
Date: 2010-12-13 Functions: 51 80 63.8 %
Branches: 492 886 55.5 %

           Branch data     Line data    Source code
       1                 :            : // $Id: TCP.cc 6916 2009-09-24 20:48:36Z vern $
       2                 :            : //
       3                 :            : // See the file "COPYING" in the main distribution directory for copyright.
       4                 :            : 
       5                 :            : 
       6                 :            : #include "Active.h"
       7                 :            : #include "PIA.h"
       8                 :            : #include "File.h"
       9                 :            : #include "TCP.h"
      10                 :            : #include "TCP_Reassembler.h"
      11                 :            : #include "TCP_Rewriter.h"
      12                 :            : #include "OSFinger.h"
      13                 :            : #include "Event.h"
      14                 :            : 
      15                 :            : namespace { // local namespace
      16                 :            :         const bool DEBUG_tcp_data_sent = false;
      17                 :            :         const bool DEBUG_tcp_connection_close = false;
      18                 :            : }
      19                 :            : 
      20                 :            : // The following are not included in all systems' tcp.h.
      21                 :            : 
      22                 :            : #ifndef TH_ECE
      23                 :            : #define TH_ECE  0x40
      24                 :            : #endif
      25                 :            : 
      26                 :            : #ifndef TH_CWR
      27                 :            : #define TH_CWR  0x80
      28                 :            : #endif
      29                 :            : 
      30                 :            : 
      31                 :            : #define TOO_LARGE_SEQ_DELTA 1048576
      32                 :            : 
      33                 :            : static const int ORIG = 1;
      34                 :            : static const int RESP = 2;
      35                 :            : 
      36                 :        938 : TCP_Analyzer::TCP_Analyzer(Connection* conn)
      37                 :        938 : : TransportLayerAnalyzer(AnalyzerTag::TCP, conn)
      38                 :            :         {
      39                 :            :         // Set a timer to eventually time out this connection.
      40                 :        938 :         ADD_ANALYZER_TIMER(&TCP_Analyzer::ExpireTimer,
      41                 :            :                                 network_time + tcp_SYN_timeout, 0,
      42                 :            :                                 TIMER_TCP_EXPIRE);
      43                 :            : 
      44                 :        938 :         deferred_gen_event = close_deferred = 0;
      45                 :            : 
      46                 :        938 :         seen_first_ACK = 0;
      47                 :        938 :         is_active = 1;
      48                 :        938 :         finished = 0;
      49                 :        938 :         reassembling = 0;
      50                 :        938 :         first_packet_seen = 0;
      51                 :        938 :         src_pkt_writer = 0;
      52                 :            : 
      53                 :        938 :         orig = new TCP_Endpoint(this, 1);
      54                 :        938 :         resp = new TCP_Endpoint(this, 0);
      55                 :            : 
      56                 :        938 :         orig->SetPeer(resp);
      57                 :        938 :         resp->SetPeer(orig);
      58                 :            : 
      59   [ -  +  #  # ]:        938 :         if ( dump_selected_source_packets )
      60                 :            :                 {
      61 [ #  # ][ #  # ]:          0 :                 if ( source_pkt_dump )
      62                 :            :                         src_pkt_writer =
      63                 :          0 :                                 new TCP_SourcePacketWriter(this, source_pkt_dump);
      64 [ #  # ][ #  # ]:          0 :                 else if ( transformed_pkt_dump )
      65                 :            :                         src_pkt_writer =
      66                 :          0 :                                 new TCP_SourcePacketWriter(this, transformed_pkt_dump);
      67                 :            :                 }
      68                 :        938 :         }
      69                 :            : 
      70                 :        938 : TCP_Analyzer::~TCP_Analyzer()
      71                 :            :         {
      72 [ -  + ][ #  # ]:        938 :         LOOP_OVER_GIVEN_CHILDREN(i, packet_children)
                 [ #  # ]
      73 [ #  # ][ #  # ]:          0 :                 delete *i;
                 [ #  # ]
      74                 :            : 
      75 [ +  - ][ #  # ]:        938 :         delete orig;
                 [ #  # ]
      76 [ +  - ][ #  # ]:        938 :         delete resp;
                 [ #  # ]
      77 [ -  + ][ #  # ]:        938 :         delete src_pkt_writer;
                 [ #  # ]
      78 [ +  - ][ #  # ]:        938 :         }
                 [ #  # ]
      79                 :            : 
      80                 :        938 : void TCP_Analyzer::Init()
      81                 :            :         {
      82                 :        938 :         Analyzer::Init();
      83         [ -  + ]:        938 :         LOOP_OVER_GIVEN_CHILDREN(i, packet_children)
      84                 :          0 :                 (*i)->Init();
      85                 :            : 
      86                 :            :         // Can't put this in construction because RewritingTrace() is virtual.
      87 [ -  + ][ #  # ]:        938 :         if ( transformed_pkt_dump && Conn()->RewritingTrace() )
                 [ -  + ]
      88                 :            :                 SetTraceRewriter(new TCP_Rewriter(this, transformed_pkt_dump,
      89                 :            :                                                 transformed_pkt_dump_MTU,
      90                 :          0 :                                                 requires_trace_commitment));
      91                 :        938 :         }
      92                 :            : 
      93                 :        938 : void TCP_Analyzer::Done()
      94                 :            :         {
      95                 :        938 :         Analyzer::Done();
      96                 :            : 
      97   [ +  -  +  + ]:        938 :         if ( connection_pending && is_active && ! BothClosed() )
         [ +  - ][ +  + ]
      98                 :        500 :                 Event(connection_pending);
      99                 :            : 
     100         [ -  + ]:        938 :         LOOP_OVER_GIVEN_CHILDREN(i, packet_children)
     101                 :          0 :                 (*i)->Done();
     102                 :            : 
     103                 :        938 :         orig->Done();
     104                 :        938 :         resp->Done();
     105                 :            : 
     106                 :        938 :         finished = 1;
     107                 :        938 :         }
     108                 :            : 
     109                 :        938 : void TCP_Analyzer::EnableReassembly()
     110                 :            :         {
     111                 :            :         SetReassembler(new TCP_Reassembler(this, this,
     112                 :            :                                         TCP_Reassembler::Forward, true, orig),
     113                 :            :                        new TCP_Reassembler(this, this,
     114                 :        938 :                                         TCP_Reassembler::Forward, false, resp));
     115                 :            : 
     116                 :        938 :         reassembling = 1;
     117                 :            : 
     118         [ -  + ]:        938 :         if ( new_connection_contents )
     119                 :          0 :                 Event(new_connection_contents);
     120                 :        938 :         }
     121                 :            : 
     122                 :            : void TCP_Analyzer::SetReassembler(TCP_Reassembler* rorig,
     123                 :        938 :                                         TCP_Reassembler* rresp)
     124                 :            :         {
     125                 :        938 :         orig->AddReassembler(rorig);
     126                 :        938 :         rorig->SetDstAnalyzer(this);
     127                 :        938 :         resp->AddReassembler(rresp);
     128                 :        938 :         rresp->SetDstAnalyzer(this);
     129                 :            : 
     130                 :        938 :         reassembling = 1;
     131                 :            : 
     132         [ -  + ]:        938 :         if ( new_connection_contents )
     133                 :          0 :                 Event(new_connection_contents);
     134                 :        938 :         }
     135                 :            : 
     136                 :            : const struct tcphdr* TCP_Analyzer::ExtractTCP_Header(const u_char*& data, 
     137                 :      17976 :                                                         int& len, int& caplen)
     138                 :            :         {
     139                 :      17976 :         const struct tcphdr* tp = (const struct tcphdr*) data;
     140                 :      17976 :         uint32 tcp_hdr_len = tp->th_off * 4;
     141                 :            : 
     142         [ -  + ]:      17976 :         if ( tcp_hdr_len < sizeof(struct tcphdr) )
     143                 :            :                 {
     144                 :          0 :                 Weird("bad_TCP_header_len");
     145                 :          0 :                 return 0;
     146                 :            :                 }
     147                 :            : 
     148 [ +  - ][ -  + ]:      17976 :         if ( tcp_hdr_len > uint32(len) ||
     149                 :            :              sizeof(struct tcphdr) > uint32(caplen) )
     150                 :            :                 {
     151                 :            :                 // This can happen even with the above test, due to TCP
     152                 :            :                 // options.
     153                 :          0 :                 Weird("truncated_header");
     154                 :          0 :                 return 0;
     155                 :            :                 }
     156                 :            : 
     157                 :      17976 :         len -= tcp_hdr_len;     // remove TCP header
     158                 :      17976 :         caplen -= tcp_hdr_len;
     159                 :      17976 :         data += tcp_hdr_len;
     160                 :            : 
     161                 :      17976 :         return tp;
     162                 :            :         }
     163                 :            : 
     164                 :            : bool TCP_Analyzer::ValidateChecksum(const struct tcphdr* tp,
     165                 :      17976 :                                 TCP_Endpoint* endpoint, int len, int caplen)
     166                 :            :         {
     167 [ +  - ][ +  - ]:      17976 :         if ( ! ignore_checksums && caplen >= len &&
         [ -  + ][ -  + ]
     168                 :            :              ! endpoint->ValidChecksum(tp, len) )
     169                 :            :                 {
     170                 :          0 :                 Weird("bad_TCP_checksum");
     171                 :          0 :                 endpoint->CheckHistory(HIST_CORRUPT_PKT, 'C');
     172                 :          0 :                 return false;
     173                 :            :                 }
     174                 :            :         else
     175                 :      17976 :                 return true;
     176                 :            :         }
     177                 :            : 
     178                 :            : void TCP_Analyzer::CheckFlagCombos(TCP_Flags flags, TCP_Endpoint* endpoint,
     179                 :      17976 :                                         uint32 base_seq, int len, int dst_port)
     180                 :            :         {
     181                 :      17976 :         bool is_orig = endpoint->IsOrig();
     182                 :            : 
     183   [ +  +  +  + ]:      17976 :         if ( is_orig && ! (first_packet_seen & ORIG) )
     184 [ +  + ][ +  + ]:        842 :                 is_partial = ! flags.SYN() || flags.ACK();
     185                 :            : 
     186 [ +  + ][ +  + ]:      17976 :         if ( ! is_orig && ! (first_packet_seen & RESP) && ! is_partial )
                 [ +  + ]
     187                 :        711 :                 is_partial = ! flags.SYN();
     188                 :            : 
     189                 :            :         int bits_set = (flags.SYN() ? 1 : 0) + (flags.FIN() ? 1 : 0) +
     190 [ +  + ][ +  + ]:      17976 :                         (flags.RST() ? 1 : 0);
                 [ +  + ]
     191         [ -  + ]:      17976 :         if ( bits_set > 1 )
     192                 :            :                 {
     193 [ #  # ][ #  # ]:          0 :                 if ( flags.FIN() && flags.RST() )
                 [ #  # ]
     194                 :          0 :                         endpoint->CheckHistory(HIST_FIN_RST_PKT, 'I');
     195                 :            :                 else
     196                 :          0 :                         endpoint->CheckHistory(HIST_MULTI_FLAG_PKT, 'Q');
     197                 :            :                 }
     198                 :            : 
     199         [ +  + ]:      17976 :         else if ( bits_set == 1 )
     200                 :            :                 {
     201         [ +  + ]:       2319 :                 if ( flags.SYN() )
     202                 :            :                         {
     203         [ +  + ]:       1042 :                         char code = flags.ACK() ? 'H' : 'S';
     204                 :            : 
     205 [ +  + ][ +  + ]:       1042 :                         if ( endpoint->CheckHistory(HIST_SYN_PKT, code) &&
                 [ +  + ]
     206                 :            :                              base_seq != endpoint->hist_last_SYN )
     207                 :         24 :                                 endpoint->AddHistory(code);
     208                 :            : 
     209                 :       1042 :                         endpoint->hist_last_SYN = base_seq;
     210                 :            :                         }
     211                 :            : 
     212         [ +  + ]:       2319 :                 if ( flags.FIN() )
     213                 :            :                         {
     214                 :            :                         // For FIN's, the sequence number comes at the
     215                 :            :                         // end of (any data in) the packet, not the
     216                 :            :                         // beginning as for SYNs and RSTs.
     217 [ +  + ][ +  + ]:       1096 :                         if ( endpoint->CheckHistory(HIST_FIN_PKT, 'F') &&
                 [ +  + ]
     218                 :            :                              base_seq + len != endpoint->hist_last_FIN )
     219                 :         66 :                                 endpoint->AddHistory('F');
     220                 :            : 
     221                 :       1096 :                         endpoint->hist_last_FIN = base_seq + len;
     222                 :            :                         }
     223                 :            : 
     224         [ +  + ]:       2319 :                 if ( flags.RST() )
     225                 :            :                         {
     226 [ +  + ][ +  + ]:        181 :                         if ( endpoint->CheckHistory(HIST_RST_PKT, 'R') &&
                 [ +  + ]
     227                 :            :                              base_seq != endpoint->hist_last_RST )
     228                 :          9 :                                 endpoint->AddHistory('R');
     229                 :            : 
     230                 :       2319 :                         endpoint->hist_last_RST = base_seq;
     231                 :            :                         }
     232                 :            :                 }
     233                 :            : 
     234                 :            :         else
     235                 :            :                 { // bits_set == 0
     236         [ +  + ]:      15657 :                 if ( len )
     237                 :       9042 :                         endpoint->CheckHistory(HIST_DATA_PKT, 'D');
     238                 :            : 
     239         [ +  - ]:       6615 :                 else if ( flags.ACK() )
     240                 :       6615 :                         endpoint->CheckHistory(HIST_ACK_PKT, 'A');
     241                 :            :                 }
     242                 :      17976 :         }
     243                 :            : 
     244                 :            : void TCP_Analyzer::UpdateWindow(TCP_Endpoint* endpoint, unsigned int window,
     245                 :            :                                 uint32 base_seq, uint32 ack_seq,
     246                 :      17976 :                                 TCP_Flags flags)
     247                 :            :         {
     248                 :            :         // Note, the offered window on an initial SYN is unscaled, even
     249                 :            :         // if the SYN includes scaling, so we need to do the following
     250                 :            :         // test *before* updating the scaling information below.  (Hmmm,
     251                 :            :         // how does this work for windows on SYN/ACKs? ###)
     252                 :      17976 :         int scale = endpoint->window_scale;
     253                 :      17976 :         window = window << scale;
     254                 :            : 
     255                 :            :         // Don't analyze window values off of SYNs, they're sometimes
     256                 :            :         // immediately rescinded.
     257         [ +  + ]:      17976 :         if ( ! flags.SYN() )
     258                 :            :                 {
     259                 :            :                 // ### Decide whether to accept new window based on Active
     260                 :            :                 // Mapping policy.
     261 [ +  + ][ +  + ]:      16934 :                 if ( int(base_seq - endpoint->window_seq) >= 0 &&
     262                 :            :                      int(ack_seq - endpoint->window_ack_seq) >= 0 )
     263                 :            :                         {
     264                 :      10511 :                         uint32 new_edge = ack_seq + window;
     265                 :      10511 :                         uint32 old_edge = endpoint->window_ack_seq + endpoint->window;
     266                 :      10511 :                         int advance = new_edge - old_edge;
     267                 :            : 
     268         [ +  + ]:      10511 :                         if ( advance < 0 )
     269                 :            :                                 {
     270                 :            :                                 // A window recision.  We don't report these
     271                 :            :                                 // for FINs or RSTs, or if the connection
     272                 :            :                                 // has already been partially closed, since
     273                 :            :                                 // such recisions occur frequently in practice,
     274                 :            :                                 // probably as the receiver loses buffer memory
     275                 :            :                                 // due to its process going away.
     276                 :            :                                 //
     277                 :            :                                 // We also, for window scaling, allow a bit
     278                 :            :                                 // of slop ###.  This is because sometimes
     279                 :            :                                 // there will be an apparent recision due
     280                 :            :                                 // to the granularity of the scaling.
     281 [ +  + ][ +  + ]:         38 :                                 if ( ! flags.FIN() && ! flags.RST() &&
         [ +  + ][ +  - ]
         [ -  + ][ -  + ]
     282                 :            :                                      endpoint->state != TCP_ENDPOINT_CLOSED &&
     283                 :            :                                      endpoint->state != TCP_ENDPOINT_RESET &&
     284                 :            :                                      (-advance) >= (1 << scale) )
     285                 :          0 :                                         Weird("window_recision");
     286                 :            :                                 }
     287                 :            : 
     288                 :      10511 :                         endpoint->window = window;
     289                 :      10511 :                         endpoint->window_ack_seq = ack_seq;
     290                 :      10511 :                         endpoint->window_seq = base_seq;
     291                 :            :                         }
     292                 :            :                 }
     293                 :      17976 :         }
     294                 :            : 
     295                 :            : void TCP_Analyzer::ProcessSYN(const IP_Hdr* ip, const struct tcphdr* tp,
     296                 :            :                                 uint32 tcp_hdr_len, int& seq_len,
     297                 :            :                                 TCP_Endpoint* endpoint, TCP_Endpoint* peer,
     298                 :            :                                 uint32 base_seq, uint32 ack_seq,
     299                 :            :                                 const uint32* orig_addr,
     300                 :       1042 :                                 int is_orig, TCP_Flags flags)
     301                 :            :         {
     302                 :       1042 :         int len = seq_len;
     303                 :            : 
     304                 :       1042 :         ++seq_len;      // SYN consumes a byte of sequence space
     305                 :            : 
     306         [ -  + ]:       1042 :         if ( flags.RST() )
     307                 :          0 :                 Weird("TCP_christmas");
     308                 :            : 
     309         [ -  + ]:       1042 :         if ( flags.URG() )
     310                 :          0 :                 Weird("baroque_SYN");
     311                 :            : 
     312         [ -  + ]:       1042 :         if ( len > 0 )
     313                 :            :                 // T/TCP definitely complicates this.
     314                 :          0 :                 Weird("SYN_with_data");
     315                 :            : 
     316                 :       1042 :         RecordVal* SYN_vals = BuildSYNPacketVal(is_orig, ip, tp)->AsRecordVal();
     317                 :            : 
     318                 :            :         // ### In the following, we could be fooled by an
     319                 :            :         // inconsistent SYN retransmission.  Where's a normalizer
     320                 :            :         // when you need one?
     321                 :            : 
     322                 :            :         // ### We know that field 5 is the window scaling ....
     323                 :       1042 :         int scale = int(SYN_vals->Lookup(5)->CoerceToInt());
     324                 :            : 
     325         [ +  + ]:       1042 :         if ( scale < 0 )
     326                 :            :                 { // no window scaling option
     327         [ +  + ]:        550 :                 if ( flags.ACK() )
     328                 :            :                         { // window scaling not negotiated
     329                 :         83 :                         endpoint->window_scale = 0;
     330                 :         83 :                         peer->window_scale = 0;
     331                 :            :                         }
     332                 :            :                 else
     333                 :            :                         // We're not offering window scaling.
     334                 :            :                         // Ideally, we'd remember this fact so that
     335                 :            :                         // if the SYN/ACK *does* include window
     336                 :            :                         // scaling, we know it won't be negotiated.
     337                 :            :                         // But it's a pain to track that, and hard
     338                 :            :                         // to see how an adversarial responder could
     339                 :            :                         // use it to evade.  Also, if we *do* want
     340                 :            :                         // to track it, we could do so using
     341                 :            :                         // connection_SYN_packet.
     342                 :        550 :                         endpoint->window_scale = 0;
     343                 :            :                 }
     344                 :            :         else
     345                 :            :                 {
     346                 :        492 :                 endpoint->window_scale = scale;
     347                 :        492 :                 endpoint->window_seq = base_seq;
     348                 :        492 :                 endpoint->window_ack_seq = ack_seq;
     349                 :            : 
     350                 :        492 :                 peer->window_seq = ack_seq;
     351                 :        492 :                 peer->window_ack_seq = base_seq;
     352                 :            :                 }
     353                 :            : 
     354         [ -  + ]:       1042 :         if ( connection_SYN_packet )
     355                 :            :                 {
     356                 :          0 :                 val_list* vl = new val_list;
     357                 :          0 :                 vl->append(BuildConnVal());
     358                 :          0 :                 vl->append(SYN_vals);
     359                 :          0 :                 ConnectionEvent(connection_SYN_packet, vl);
     360                 :            :                 }
     361                 :            :         else
     362                 :       1042 :                 Unref(SYN_vals);
     363                 :            : 
     364                 :            :         // Passive fingerprinting.
     365                 :            :         //
     366                 :            :         // is_orig will be removed once we can do SYN-ACK fingerprinting.
     367 [ -  + ][ #  # ]:       1042 :         if ( OS_version_found && is_orig )
                 [ -  + ]
     368                 :            :                 {
     369                 :          0 :                 Val src_addr_val(orig_addr, TYPE_ADDR);
     370   [ #  #  #  # ]:          0 :                 if ( generate_OS_version_event->Size() == 0 ||
                 [ #  # ]
     371                 :            :                      generate_OS_version_event->Lookup(&src_addr_val) )
     372                 :            :                         {
     373                 :            :                         RecordVal* OS_val =
     374                 :          0 :                                 BuildOSVal(is_orig, ip, tp, tcp_hdr_len);
     375         [ #  # ]:          0 :                         if ( OS_val )
     376                 :            :                                 { // found new OS version
     377                 :          0 :                                 val_list* vl = new val_list;
     378                 :          0 :                                 vl->append(BuildConnVal());
     379                 :          0 :                                 vl->append(new AddrVal(orig_addr));
     380                 :          0 :                                 vl->append(OS_val);
     381                 :          0 :                                 ConnectionEvent(OS_version_found, vl);
     382                 :            :                                 }
     383                 :          0 :                         }
     384                 :            :                 }
     385                 :       1042 :         }
     386                 :            : 
     387                 :            : void TCP_Analyzer::ProcessFIN(double t, TCP_Endpoint* endpoint,
     388                 :       1096 :                                 int& seq_len, uint32 base_seq)
     389                 :            :         {
     390         [ +  + ]:       1096 :         if ( endpoint->FIN_cnt == 0 )
     391                 :            :                 {
     392                 :        937 :                 ++seq_len;      // FIN consumes a byte of sequence space
     393                 :        937 :                 ++endpoint->FIN_cnt; // remember that we've seen a FIN
     394                 :            :                 }
     395                 :            : 
     396 [ +  + ][ -  + ]:        159 :         else if ( t < endpoint->last_time + tcp_storm_interarrival_thresh &&
                 [ -  + ]
     397                 :            :                   ++endpoint->FIN_cnt == tcp_storm_thresh )
     398                 :          0 :                 Weird("FIN_storm");
     399                 :            : 
     400                 :            :         // Remember the relative seq in FIN_seq.
     401                 :       1096 :         endpoint->FIN_seq = base_seq - endpoint->StartSeq() + seq_len;
     402                 :       1096 :         }
     403                 :            : 
     404                 :            : bool TCP_Analyzer::ProcessRST(double t, TCP_Endpoint* endpoint,
     405                 :            :                                 const IP_Hdr* ip, uint32 base_seq,
     406                 :        181 :                                 int len, int& seq_len)
     407                 :            :         {
     408 [ +  + ][ -  + ]:        181 :         if ( t < endpoint->last_time + tcp_storm_interarrival_thresh &&
                 [ -  + ]
     409                 :            :              ++endpoint->RST_cnt == tcp_storm_thresh )
     410                 :          0 :                 Weird("RST_storm");
     411                 :            : 
     412         [ +  + ]:        181 :         else if ( endpoint->RST_cnt == 0 )
     413                 :        132 :                 ++endpoint->RST_cnt; // Remember we've seen a RST
     414                 :            : 
     415                 :            : #ifdef ACTIVE_MAPPING
     416                 :            : //              if ( peer->state == TCP_ENDPOINT_INACTIVE )
     417                 :            : //                  debug_msg("rst while inactive\n"); // ### Cold-start: what to do?
     418                 :            : //              else
     419                 :            : 
     420                 :            :         const NumericData* AM_policy;
     421                 :            :         get_map_result(ip->DstAddr4(), AM_policy);
     422                 :            : 
     423                 :            :         if ( base_seq == endpoint->AckSeq() )
     424                 :            :                 ;        // everyone should accept a RST in sequence
     425                 :            : 
     426                 :            :         else if ( endpoint->window == 0 )
     427                 :            :                 ; // ### Cold Start: we don't know the window,
     428                 :            :                   // so just go along for now
     429                 :            : 
     430                 :            :         else
     431                 :            :                 {
     432                 :            :                 uint32 right_edge = endpoint->AckSeq() +
     433                 :            :                         (endpoint->window << endpoint->window_scale);
     434                 :            : 
     435                 :            :                 if ( base_seq < right_edge  )
     436                 :            :                         {
     437                 :            :                         if ( ! AM_policy->accepts_rst_in_window )
     438                 :            :                                 {
     439                 :            : #if 0
     440                 :            :                                 debug_msg("Machine does not accept RST merely in window; ignoring. t=%.6f,base=%u, ackseq=%u, window=%hd \n",
     441                 :            :                                         network_time, base_seq, endpoint->AckSeq(), window);
     442                 :            : #endif
     443                 :            :                                 return false;
     444                 :            :                                 }
     445                 :            :                         }
     446                 :            : 
     447                 :            :                 else if ( ! AM_policy->accepts_rst_outside_window )
     448                 :            :                         {
     449                 :            : #if 0
     450                 :            :                         debug_msg("Machine does not accept RST outside window; ignoring. t=%.6f,base=%u, ackseq=%u, window=%hd \n",
     451                 :            :                                 network_time, base_seq, endpoint->AckSeq(), window);
     452                 :            : #endif
     453                 :            :                         return false;
     454                 :            :                         }
     455                 :            :                 }
     456                 :            : #endif
     457                 :            : 
     458         [ +  + ]:        181 :         if ( len > 0 )
     459                 :            :                 {
     460                 :            :                 // This now happens often enough that it's
     461                 :            :                 // not in the least interesting.
     462                 :            :                 // Weird("RST_with_data");
     463                 :            : 
     464                 :            :                 // Don't include the data in the computation of
     465                 :            :                 // the sequence space for this connection, as
     466                 :            :                 // it's not in fact part of the TCP stream.
     467                 :         85 :                 seq_len = 0;
     468                 :            :                 }
     469                 :            : 
     470                 :        181 :         PacketWithRST();
     471                 :            : 
     472                 :        181 :         return true;
     473                 :            :         }
     474                 :            : 
     475                 :            : int TCP_Analyzer::ProcessFlags(double t,
     476                 :            :                                 const IP_Hdr* ip, const struct tcphdr* tp,
     477                 :            :                                 uint32 tcp_hdr_len, int len, int& seq_len,
     478                 :            :                                 TCP_Endpoint* endpoint, TCP_Endpoint* peer,
     479                 :            :                                 uint32 base_seq, uint32 ack_seq,
     480                 :            :                                 const uint32* orig_addr,
     481                 :      17976 :                                 int is_orig, TCP_Flags flags)
     482                 :            :         {
     483         [ +  + ]:      17976 :         if ( flags.SYN() )
     484                 :            :                 ProcessSYN(ip, tp, tcp_hdr_len, seq_len, endpoint, peer,
     485                 :       1042 :                                 base_seq, ack_seq, orig_addr, is_orig, flags);
     486                 :            : 
     487         [ +  + ]:      17976 :         if ( flags.FIN() )
     488                 :       1096 :                 ProcessFIN(t, endpoint, seq_len, base_seq);
     489                 :            : 
     490 [ +  + ][ -  + ]:      17976 :         if ( flags.RST() &&
                 [ -  + ]
     491                 :            :              ! ProcessRST(t, endpoint, ip, base_seq, len, seq_len) )
     492                 :          0 :                 return 0;
     493                 :            : 
     494         [ +  + ]:      17976 :         if ( flags.ACK() )
     495                 :      17321 :                 ProcessACK(endpoint, peer, ack_seq, is_orig, flags);
     496                 :            : 
     497                 :      17976 :         return 1;
     498                 :            :         }
     499                 :            : 
     500                 :            : void TCP_Analyzer::TransitionFromInactive(double t, TCP_Endpoint* endpoint,
     501                 :            :                                                 uint32 base_seq,
     502                 :       1732 :                                                 uint32 last_seq, int SYN)
     503                 :            :         {
     504         [ +  + ]:       1732 :         if ( SYN )
     505                 :            :                 {
     506                 :            :                 // ## endpoint->AckSeq() = endpoint->start_seq = base_seq;
     507                 :        989 :                 endpoint->InitAckSeq(base_seq);
     508                 :        989 :                 endpoint->InitStartSeq(base_seq);
     509                 :            :                 }
     510                 :            :         else
     511                 :            :                 {
     512                 :            :                 // This is a partial connection - set up the
     513                 :            :                 // initial sequence numbers as though we saw
     514                 :            :                 // a SYN, to keep the relative byte numbering
     515                 :            :                 // consistent.
     516                 :            :                 // ## endpoint->AckSeq() = endpoint->start_seq = base_seq - 1;
     517                 :        743 :                 endpoint->InitAckSeq(base_seq - 1);
     518                 :        743 :                 endpoint->InitStartSeq(base_seq - 1);
     519                 :            :                 }
     520                 :            : 
     521                 :            :         // ## endpoint->last_seq = last_seq;
     522                 :       1732 :         endpoint->InitLastSeq(last_seq);
     523                 :       1732 :         endpoint->start_time = t;
     524                 :       1732 :         }
     525                 :            : 
     526                 :            : int TCP_Analyzer::UpdateLastSeq(TCP_Endpoint* endpoint, uint32 last_seq,
     527                 :      17976 :                                         TCP_Flags flags)
     528                 :            :         {
     529                 :      17976 :         int delta_last = seq_delta(last_seq, endpoint->LastSeq());
     530                 :            : 
     531   [ +  +  +  + ]:      17976 :         if ( (flags.SYN() || flags.RST()) &&
         [ +  + ][ +  + ]
                 [ +  + ]
     532                 :            :              (delta_last > TOO_LARGE_SEQ_DELTA ||
     533                 :            :               delta_last < -TOO_LARGE_SEQ_DELTA) )
     534                 :            :                 // ### perhaps trust RST seq #'s if initial and not too
     535                 :            :                 // outlandish, but not if they're coming after the other
     536                 :            :                 // side has sent a FIN - trust the FIN ack instead
     537                 :            :                 ;
     538                 :            : 
     539 [ +  + ][ +  + ]:      17946 :         else if ( flags.FIN() &&
                 [ +  + ]
     540                 :            :                   endpoint->LastSeq() == endpoint->StartSeq() + 1 )
     541                 :            :                 // Update last_seq based on the FIN even if delta_last < 0.
     542                 :            :                 // This is to accommodate > 2 GB connections for which
     543                 :            :                 // we've only seen the SYN and the FIN (hence the check
     544                 :            :                 // for last_seq == start_seq + 1).
     545                 :         67 :                 endpoint->UpdateLastSeq(last_seq);
     546                 :            : 
     547         [ +  + ]:      17879 :         else if ( endpoint->state == TCP_ENDPOINT_RESET )
     548                 :            :                 // don't trust any subsequent sequence numbers
     549                 :            :                 ;
     550                 :            : 
     551         [ +  + ]:      17864 :         else if ( delta_last > 0 )
     552                 :            :                 // ### check for large jumps here.
     553                 :            :                 // ## endpoint->last_seq = last_seq;
     554                 :       9142 :                 endpoint->UpdateLastSeq(last_seq);
     555                 :            : 
     556                 :            :         else if ( delta_last <= 0 )
     557                 :            :                 { // ### ++retransmit, unless this is a pure ack
     558                 :            :                 }
     559                 :            : 
     560                 :      17976 :         return delta_last;
     561                 :            :         }
     562                 :            : 
     563                 :            : void TCP_Analyzer::ProcessACK(TCP_Endpoint* endpoint, TCP_Endpoint* peer,
     564                 :            :                                 uint32 ack_seq, int is_orig,
     565                 :      17321 :                                 TCP_Flags flags)
     566                 :            :         {
     567 [ +  + ][ +  + ]:      17321 :         if ( is_orig && ! seen_first_ACK &&
         [ +  + ][ +  + ]
     568                 :            :              (endpoint->state == TCP_ENDPOINT_ESTABLISHED ||
     569                 :            :               endpoint->state == TCP_ENDPOINT_SYN_SENT) )
     570                 :            :                 {
     571                 :        453 :                 seen_first_ACK = 1;
     572                 :        453 :                 Event(connection_first_ACK);
     573                 :            :                 }
     574                 :            : 
     575         [ +  + ]:      17321 :         if ( peer->state == TCP_ENDPOINT_INACTIVE )
     576                 :            :                 {
     577 [ +  + ][ +  + ]:        797 :                 if ( ! flags.SYN() && ! flags.FIN() && ! flags.RST() )
         [ +  + ][ +  + ]
     578                 :            :                         {
     579 [ +  + ][ +  - ]:        565 :                         if ( endpoint->state == TCP_ENDPOINT_SYN_SENT ||
                 [ -  + ]
     580                 :            :                              endpoint->state == TCP_ENDPOINT_SYN_ACK_SENT ||
     581                 :            :                              endpoint->state == TCP_ENDPOINT_ESTABLISHED )
     582                 :            :                                 {
     583                 :            :                                 // We've already sent a SYN, but that
     584                 :            :                                 // hasn't roused the other end, yet we're
     585                 :            :                                 // ack'ing their data.
     586                 :            : 
     587         [ +  + ]:          3 :                                 if ( ! Conn()->DidWeird() )
     588                 :          1 :                                         Weird("possible_split_routing");
     589                 :            :                                 }
     590                 :            :                         }
     591                 :            : 
     592                 :            :                 // Start the sequence numbering as if there was an initial
     593                 :            :                 // SYN, so the relative numbering of subsequent data packets
     594                 :            :                 // stays consistent.
     595                 :            :                 // ## peer->start_seq = peer->AckSeq() = peer->last_seq =
     596                 :            :                 // ##   ack_seq - 1;
     597                 :        797 :                 peer->InitStartSeq(ack_seq - 1);
     598                 :        797 :                 peer->InitAckSeq(ack_seq - 1);
     599                 :        797 :                 peer->InitLastSeq(ack_seq - 1);
     600                 :            :                 }
     601                 :            : 
     602         [ +  + ]:      16524 :         else if ( ! flags.RST() )
     603                 :            :                 { // don't trust ack's in RST packets
     604                 :      16518 :                 int delta_ack = seq_delta(ack_seq, peer->AckSeq());
     605   [ -  +  #  # ]:      16518 :                 if ( ack_seq == 0 && delta_ack > TOO_LARGE_SEQ_DELTA )
     606                 :            :                         // More likely that this is a broken ack than a
     607                 :            :                         // large connection that happens to land on 0 in the
     608                 :            :                         // sequence space.
     609                 :            :                         ;
     610                 :            : 
     611         [ +  + ]:      16518 :                 else if ( delta_ack > 0 )
     612                 :       7355 :                         peer->UpdateAckSeq(ack_seq);
     613                 :            :                 }
     614                 :            : 
     615                 :      17321 :         peer->AckReceived(ack_seq - peer->StartSeq());
     616                 :      17321 :         }
     617                 :            : 
     618                 :            : void TCP_Analyzer::UpdateInactiveState(double t,
     619                 :            :                         TCP_Endpoint* endpoint, TCP_Endpoint* peer,
     620                 :            :                         uint32 base_seq, uint32 ack_seq,
     621                 :            :                         int len, int is_orig, TCP_Flags flags,
     622                 :       1732 :                         int& do_close, int& gen_event)
     623                 :            :         {
     624         [ +  + ]:       1732 :         if ( flags.SYN() )
     625                 :            :                 {
     626         [ +  + ]:        989 :                 if ( is_orig )
     627                 :            :                         {
     628         [ +  + ]:        479 :                         if ( flags.ACK() )
     629                 :            :                                 {
     630                 :          2 :                                 Weird("connection_originator_SYN_ack");
     631                 :          2 :                                 endpoint->SetState(TCP_ENDPOINT_SYN_ACK_SENT);
     632                 :            :                                 }
     633                 :            :                         else
     634                 :        477 :                                 endpoint->SetState(TCP_ENDPOINT_SYN_SENT);
     635                 :            : 
     636         [ +  - ]:        479 :                         if ( connection_attempt )
     637                 :        479 :                                 ADD_ANALYZER_TIMER(&TCP_Analyzer::AttemptTimer,
     638                 :            :                                         t + tcp_attempt_delay, 1,
     639                 :            :                                         TIMER_TCP_ATTEMPT);
     640                 :            :                         }
     641                 :            :                 else
     642                 :            :                         {
     643         [ +  - ]:        510 :                         if ( flags.ACK() )
     644                 :            :                                 {
     645 [ +  + ][ +  - ]:        510 :                                 if ( peer->state != TCP_ENDPOINT_INACTIVE &&
         [ +  + ][ +  + ]
     646                 :            :                                      peer->state != TCP_ENDPOINT_PARTIAL &&
     647                 :            :                                      ! seq_between(ack_seq, peer->StartSeq(), peer->LastSeq()) )
     648                 :        510 :                                         Weird("bad_SYN_ack");
     649                 :            :                                 }
     650                 :            : 
     651 [ #  # ][ #  # ]:          0 :                         else if ( peer->state == TCP_ENDPOINT_SYN_ACK_SENT &&
                 [ #  # ]
     652                 :            :                                   base_seq == endpoint->StartSeq() )
     653                 :            :                                 {
     654                 :            :                                 // This is a SYN/SYN-ACK reversal,
     655                 :            :                                 // per the discussion in IsReuse.
     656                 :            :                                 // Flip the endpoints and establish
     657                 :            :                                 // the connection.
     658                 :          0 :                                 Conn()->FlipRoles();
     659                 :          0 :                                 peer->SetState(TCP_ENDPOINT_ESTABLISHED);
     660                 :            :                                 }
     661                 :            : 
     662                 :            :                         else
     663                 :          0 :                                 Weird("simultaneous_open");
     664                 :            : 
     665         [ +  + ]:        510 :                         if ( peer->state == TCP_ENDPOINT_SYN_SENT )
     666                 :        448 :                                 peer->SetState(TCP_ENDPOINT_ESTABLISHED);
     667         [ +  - ]:         62 :                         else if ( peer->state == TCP_ENDPOINT_INACTIVE )
     668                 :            :                                 {
     669                 :            :                                 // If we were to ignore SYNs and
     670                 :            :                                 // only instantiate state on SYN
     671                 :            :                                 // acks, then we'd do:
     672                 :            :                                 //    peer->SetState(TCP_ENDPOINT_ESTABLISHED);
     673                 :            :                                 // here.
     674                 :         62 :                                 Weird("unsolicited_SYN_response");
     675                 :            :                                 }
     676                 :            : 
     677                 :        510 :                         endpoint->SetState(TCP_ENDPOINT_ESTABLISHED);
     678                 :            : 
     679         [ +  - ]:        510 :                         if ( peer->state != TCP_ENDPOINT_PARTIAL )
     680                 :            :                                 {
     681                 :        510 :                                 Event(connection_established);
     682                 :        510 :                                 Conn()->EnableStatusUpdateTimer();
     683                 :            :                                 }
     684                 :            :                         }
     685                 :            :                 }
     686                 :            : 
     687         [ +  + ]:       1732 :         if ( flags.FIN() )
     688                 :            :                 {
     689                 :        144 :                 endpoint->SetState(TCP_ENDPOINT_CLOSED);
     690                 :        144 :                 do_close = gen_event = 1;
     691   [ +  +  +  - ]:        144 :                 if ( peer->state != TCP_ENDPOINT_PARTIAL && ! flags.SYN() )
                 [ +  + ]
     692                 :        136 :                         Weird("spontaneous_FIN");
     693                 :            :                 }
     694                 :            : 
     695         [ +  + ]:       1732 :         if ( flags.RST() )
     696                 :            :                 {
     697                 :         80 :                 endpoint->SetState(TCP_ENDPOINT_RESET);
     698                 :            : 
     699                 :         80 :                 int is_reject = 0;
     700                 :            : 
     701         [ +  + ]:         80 :                 if ( is_orig )
     702                 :            :                         {
     703                 :            :                         // If our peer is established then we saw
     704                 :            :                         // a SYN-ack but not SYN - so a reverse
     705                 :            :                         // scan, and we should treat this as a
     706                 :            :                         // reject.
     707         [ -  + ]:         14 :                         if ( peer->state == TCP_ENDPOINT_ESTABLISHED )
     708                 :         14 :                                 is_reject = 1;
     709                 :            :                         }
     710                 :            : 
     711 [ +  + ][ -  + ]:         66 :                 else if ( peer->state == TCP_ENDPOINT_SYN_SENT ||
     712                 :            :                           peer->state == TCP_ENDPOINT_SYN_ACK_SENT )
     713                 :            :                         // We're rejecting an initial SYN.
     714                 :          4 :                         is_reject = 1;
     715                 :            : 
     716                 :         80 :                 do_close = 1;
     717                 :         80 :                 gen_event = ! is_reject;
     718                 :            : 
     719         [ +  + ]:         80 :                 if ( is_reject )
     720                 :          4 :                         Event(connection_rejected);
     721                 :            : 
     722         [ +  + ]:         76 :                 else if ( peer->state == TCP_ENDPOINT_INACTIVE )
     723                 :         34 :                         Weird("spontaneous_RST");
     724                 :            :                 }
     725                 :            : 
     726         [ +  + ]:       1732 :         if ( endpoint->state == TCP_ENDPOINT_INACTIVE )
     727                 :            :                 { // No control flags to change the state.
     728 [ +  + ][ +  + ]:        519 :                 if ( ! is_orig && len == 0 &&
                 [ +  + ]
     729                 :            :                      orig->state == TCP_ENDPOINT_SYN_SENT )
     730                 :            :                         // Some eccentric TCP's will ack an initial
     731                 :            :                         // SYN prior to sending a SYN reply (hello,
     732                 :            :                         // ftp.microsoft.com).  For those, don't
     733                 :            :                         // consider the ack as forming a partial
     734                 :            :                         // connection.
     735                 :            :                         ;
     736                 :            :                 else
     737                 :            :                         {
     738                 :        508 :                         endpoint->SetState(TCP_ENDPOINT_PARTIAL);
     739                 :        508 :                         Conn()->EnableStatusUpdateTimer();
     740                 :            :                         
     741         [ +  + ]:        508 :                         if ( peer->state == TCP_ENDPOINT_PARTIAL )
     742                 :            :                                 // We've seen both sides of a partial
     743                 :            :                                 // connection, report it.
     744                 :        149 :                                 Event(partial_connection);
     745                 :            :                         }
     746                 :            :                 }
     747                 :       1732 :         }
     748                 :            : 
     749                 :            : void TCP_Analyzer::UpdateSYN_SentState(double t,
     750                 :            :                         TCP_Endpoint* endpoint, TCP_Endpoint* peer,
     751                 :            :                         uint32 base_seq, uint32 last_seq,
     752                 :            :                         int len, int is_orig, TCP_Flags flags,
     753                 :        396 :                         int& do_close, int& gen_event)
     754                 :            :         {
     755         [ -  + ]:        396 :         if ( flags.SYN() )
     756                 :            :                 {
     757         [ #  # ]:          0 :                 if ( is_orig )
     758                 :            :                         {
     759 [ #  # ][ #  # ]:          0 :                         if ( flags.ACK() && ! flags.FIN() && ! flags.RST() &&
         [ #  # ][ #  # ]
                 [ #  # ]
     760                 :            :                              endpoint->state != TCP_ENDPOINT_SYN_ACK_SENT )
     761                 :          0 :                                 Weird("repeated_SYN_with_ack");
     762                 :            :                         }
     763                 :            :                 else
     764                 :            :                         {
     765 [ #  # ][ #  # ]:          0 :                         if ( ! flags.ACK() &&
                 [ #  # ]
     766                 :            :                              endpoint->state != TCP_ENDPOINT_SYN_SENT )
     767                 :          0 :                                 Weird("repeated_SYN_reply_wo_ack");
     768                 :            :                         }
     769                 :            : 
     770         [ #  # ]:          0 :                 if ( base_seq != endpoint->StartSeq() )
     771                 :            :                         {
     772                 :          0 :                         Weird("SYN_seq_jump");
     773                 :            :                         // ## endpoint->AckSeq() = endpoint->start_seq = base_seq;
     774                 :            :                         // ## endpoint->last_seq = last_seq;
     775                 :          0 :                         endpoint->InitStartSeq(base_seq);
     776                 :          0 :                         endpoint->InitAckSeq(base_seq);
     777                 :          0 :                         endpoint->InitLastSeq(last_seq);
     778                 :            :                         }
     779                 :            :                 }
     780                 :            : 
     781         [ +  + ]:        396 :         if ( flags.FIN() )
     782                 :            :                 {
     783 [ +  - ][ -  + ]:          7 :                 if ( peer->state == TCP_ENDPOINT_INACTIVE ||
     784                 :            :                      peer->state == TCP_ENDPOINT_SYN_SENT )
     785                 :          0 :                         Weird("inappropriate_FIN");
     786                 :            : 
     787                 :          7 :                 endpoint->SetState(TCP_ENDPOINT_CLOSED);
     788                 :          7 :                 do_close = gen_event = 1;
     789                 :            :                 }
     790                 :            : 
     791         [ -  + ]:        396 :         if ( flags.RST() )
     792                 :            :                 {
     793                 :          0 :                 endpoint->SetState(TCP_ENDPOINT_RESET);
     794                 :          0 :                 ConnectionReset();
     795                 :          0 :                 do_close = 1;
     796                 :            :                 }
     797                 :            : 
     798         [ +  + ]:        396 :         else if ( len > 0 )
     799                 :         67 :                 Weird("data_before_established");
     800                 :        396 :         }
     801                 :            : 
     802                 :            : void TCP_Analyzer::UpdateEstablishedState(double t,
     803                 :            :                         TCP_Endpoint* endpoint, TCP_Endpoint* peer,
     804                 :            :                         uint32 base_seq, uint32 last_seq,
     805                 :            :                         int is_orig, TCP_Flags flags,
     806                 :      15073 :                         int& do_close, int& gen_event)
     807                 :            :         {
     808         [ +  + ]:      15073 :         if ( flags.SYN() )
     809                 :            :                 {
     810 [ -  + ][ #  # ]:         53 :                 if ( endpoint->state == TCP_ENDPOINT_PARTIAL &&
         [ #  # ][ -  + ]
     811                 :            :                      peer->state == TCP_ENDPOINT_INACTIVE && ! flags.ACK() )
     812                 :            :                         {
     813                 :          0 :                         Weird("SYN_after_partial");
     814                 :          0 :                         endpoint->SetState(TCP_ENDPOINT_SYN_SENT);
     815                 :            :                         }
     816                 :            : 
     817         [ -  + ]:         53 :                 if ( endpoint->Size() > 0 )
     818                 :          0 :                         Weird("SYN_inside_connection");
     819                 :            : 
     820         [ +  + ]:         53 :                 if ( base_seq != endpoint->StartSeq() )
     821                 :         24 :                         Weird("SYN_seq_jump");
     822                 :            : 
     823                 :            :                 // Make a guess that somehow the connection didn't
     824                 :            :                 // get established, and this SYN will be the
     825                 :            :                 // one that actually sets it up.
     826                 :            :                 // ## endpoint->AckSeq() = endpoint->start_seq = base_seq;
     827                 :            :                 // ## endpoint->last_seq = last_seq;
     828                 :         53 :                 endpoint->InitStartSeq(base_seq);
     829                 :         53 :                 endpoint->InitAckSeq(base_seq);
     830                 :         53 :                 endpoint->InitLastSeq(last_seq);
     831                 :            :                 }
     832                 :            : 
     833 [ +  + ][ +  - ]:      15073 :         if ( flags.FIN() && ! flags.RST() )     // ###
                 [ +  + ]
     834                 :            :                 { // should check sequence/ack numbers here ###
     835                 :        786 :                 endpoint->SetState(TCP_ENDPOINT_CLOSED);
     836                 :            : 
     837   [ +  +  +  + ]:        786 :                 if ( peer->state == TCP_ENDPOINT_RESET &&
     838                 :            :                      peer->prev_state == TCP_ENDPOINT_CLOSED )
     839                 :            :                         // The peer sent a FIN followed by a RST.
     840                 :            :                         // Turn it back into CLOSED state, because
     841                 :            :                         // this was actually normal termination.
     842                 :          4 :                         peer->SetState(TCP_ENDPOINT_CLOSED);
     843                 :            : 
     844                 :        786 :                 do_close = gen_event = 1;
     845                 :            :                 }
     846                 :            : 
     847         [ +  + ]:      15073 :         if ( flags.RST() )
     848                 :            :                 {
     849                 :         26 :                 endpoint->SetState(TCP_ENDPOINT_RESET);
     850                 :         26 :                 do_close = 1;
     851                 :            : 
     852   [ -  +  #  # ]:         26 :                 if ( peer->state != TCP_ENDPOINT_RESET ||
     853                 :            :                      peer->prev_state != TCP_ENDPOINT_ESTABLISHED )
     854                 :         26 :                         ConnectionReset();
     855                 :            :                 }
     856                 :      15073 :         }
     857                 :            : 
     858                 :            : void TCP_Analyzer::UpdateClosedState(double t, TCP_Endpoint* endpoint,
     859                 :        760 :                                 int delta_last, TCP_Flags flags, int& do_close)
     860                 :            :         {
     861         [ -  + ]:        760 :         if ( flags.SYN() )
     862                 :          0 :                 Weird("SYN_after_close");
     863                 :            : 
     864 [ +  + ][ +  + ]:        760 :         if ( flags.FIN() && delta_last > 0 )
                 [ +  + ]
     865                 :            :                 // Probably should also complain on FIN recision.
     866                 :            :                 // That requires an extra state variable to avoid
     867                 :            :                 // generating slews of weird's when a TCP gets
     868                 :            :                 // seriously confused (this from experience).
     869                 :         12 :                 Weird("FIN_advanced_last_seq");
     870                 :            : 
     871                 :            :         // Previously, our state was CLOSED, since we sent a FIN.
     872                 :            :         // If our peer was also closed, then don't change our state
     873                 :            :         // now on a RST, since this connection has already seen a FIN
     874                 :            :         // exchange.
     875 [ +  + ][ +  + ]:        760 :         if ( flags.RST() && endpoint->peer->state != TCP_ENDPOINT_CLOSED )
                 [ +  + ]
     876                 :            :                 {
     877                 :         37 :                 endpoint->SetState(TCP_ENDPOINT_RESET);
     878                 :            : 
     879         [ +  + ]:         37 :                 if ( ! endpoint->did_close )
     880                 :            :                         // RST after FIN.
     881                 :          4 :                         do_close = 1;
     882                 :            : 
     883         [ +  - ]:         37 :                 if ( connection_reset )
     884                 :         37 :                         ADD_ANALYZER_TIMER(&TCP_Analyzer::ResetTimer,
     885                 :            :                                         t + tcp_reset_delay, 1,
     886                 :            :                                         TIMER_TCP_RESET);
     887                 :            :                 }
     888                 :        760 :         }
     889                 :            : 
     890                 :         15 : void TCP_Analyzer::UpdateResetState(int len, TCP_Flags flags)
     891                 :            :         {
     892         [ -  + ]:         15 :         if ( flags.SYN() )
     893                 :          0 :                 Weird("SYN_after_reset");
     894         [ -  + ]:         15 :         if ( flags.FIN() )
     895                 :          0 :                 Weird("FIN_after_reset");
     896                 :            : 
     897 [ +  + ][ -  + ]:         15 :         if ( len > 0 && ! flags.RST() )
                 [ -  + ]
     898                 :          0 :                 Weird("data_after_reset");
     899                 :         15 :         }
     900                 :            : 
     901                 :            : void TCP_Analyzer::UpdateStateMachine(double t,
     902                 :            :                         TCP_Endpoint* endpoint, TCP_Endpoint* peer,
     903                 :            :                         uint32 base_seq, uint32 ack_seq, uint32 last_seq,
     904                 :            :                         int len, int delta_last, int is_orig, TCP_Flags flags,
     905                 :      17976 :                         int& do_close, int& gen_event)
     906                 :            :         {
     907                 :      17976 :         do_close = 0;   // whether to report the connection as closed
     908                 :      17976 :         gen_event = 0;  // if so, whether to generate an event
     909                 :            : 
     910 [ +  +  +  +  + :      17976 :         switch ( endpoint->state ) {
                      - ]
     911                 :            : 
     912                 :            :         case TCP_ENDPOINT_INACTIVE:
     913                 :            :                 UpdateInactiveState(t, endpoint, peer, base_seq, ack_seq,
     914                 :            :                                         len, is_orig, flags,
     915                 :       1732 :                                         do_close, gen_event);
     916                 :       1732 :                 break;
     917                 :            : 
     918                 :            :         case TCP_ENDPOINT_SYN_SENT:
     919                 :            :         case TCP_ENDPOINT_SYN_ACK_SENT:
     920                 :            :                 UpdateSYN_SentState(t, endpoint, peer, base_seq, last_seq,
     921                 :            :                                         len, is_orig, flags,
     922                 :        396 :                                         do_close, gen_event);
     923                 :        396 :                 break;
     924                 :            : 
     925                 :            :         case TCP_ENDPOINT_ESTABLISHED:
     926                 :            :         case TCP_ENDPOINT_PARTIAL:
     927                 :            :                 UpdateEstablishedState(t, endpoint, peer, base_seq, last_seq,
     928                 :      15073 :                                         is_orig, flags, do_close, gen_event);
     929                 :      15073 :                 break;
     930                 :            : 
     931                 :            :         case TCP_ENDPOINT_CLOSED:
     932                 :        760 :                 UpdateClosedState(t, endpoint, delta_last, flags, do_close);
     933                 :        760 :                 break;
     934                 :            : 
     935                 :            :         case TCP_ENDPOINT_RESET:
     936                 :         15 :                 UpdateResetState(len, flags);
     937                 :            :                 break;
     938                 :            :         }
     939                 :      17976 :         }
     940                 :            : 
     941                 :            : void TCP_Analyzer::GeneratePacketEvent(TCP_Endpoint* endpoint,
     942                 :            :                                         TCP_Endpoint* peer,
     943                 :            :                                         uint32 base_seq, uint32 ack_seq,
     944                 :            :                                         const u_char* data, int len, int caplen,
     945                 :          0 :                                         int is_orig, TCP_Flags flags)
     946                 :            :         {
     947                 :            :         char tcp_flags[256];
     948                 :          0 :         int tcp_flag_len = 0;
     949                 :            : 
     950         [ #  # ]:          0 :         if ( flags.SYN() ) tcp_flags[tcp_flag_len++] = 'S';
     951         [ #  # ]:          0 :         if ( flags.FIN() ) tcp_flags[tcp_flag_len++] = 'F';
     952         [ #  # ]:          0 :         if ( flags.RST() ) tcp_flags[tcp_flag_len++] = 'R';
     953         [ #  # ]:          0 :         if ( flags.ACK() ) tcp_flags[tcp_flag_len++] = 'A';
     954         [ #  # ]:          0 :         if ( flags.PUSH() ) tcp_flags[tcp_flag_len++] = 'P';
     955         [ #  # ]:          0 :         if ( flags.URG() ) tcp_flags[tcp_flag_len++] = 'U';
     956                 :            : 
     957                 :          0 :         tcp_flags[tcp_flag_len] = '\0';
     958                 :            : 
     959                 :          0 :         val_list* vl = new val_list();
     960                 :            : 
     961                 :          0 :         vl->append(BuildConnVal());
     962                 :          0 :         vl->append(new Val(is_orig, TYPE_BOOL));
     963                 :          0 :         vl->append(new StringVal(tcp_flags));
     964                 :          0 :         vl->append(new Val(base_seq - endpoint->StartSeq(), TYPE_COUNT));
     965                 :            :         vl->append(new Val(flags.ACK() ?
     966         [ #  # ]:          0 :                         ack_seq - peer->StartSeq() : 0, TYPE_COUNT));
     967                 :          0 :         vl->append(new Val(len, TYPE_COUNT));
     968                 :            : 
     969                 :            :         // We need the min() here because Ethernet padding can lead to
     970                 :            :         // caplen > len.
     971                 :          0 :         vl->append(new StringVal(min(caplen, len), (const char*) data));
     972                 :            : 
     973                 :          0 :         ConnectionEvent(tcp_packet, vl);
     974                 :          0 :         }
     975                 :            : 
     976                 :            : int TCP_Analyzer::DeliverData(double t, const u_char* data, int len, int caplen,
     977                 :            :                                 const IP_Hdr* ip, const struct tcphdr* tp,
     978                 :            :                                 TCP_Endpoint* endpoint, uint32 base_seq,
     979                 :       9174 :                                 int is_orig, TCP_Flags flags)
     980                 :            :         {
     981                 :       9174 :         int data_seq = base_seq - endpoint->StartSeq();
     982         [ -  + ]:       9174 :         if ( flags.SYN() )
     983                 :          0 :                 ++data_seq;     // skip over SYN octet
     984                 :            : 
     985                 :            :         int need_contents = endpoint->DataSent(t, data_seq,
     986                 :       9174 :                                         len, caplen, data, ip, tp);
     987                 :            : 
     988         [ -  + ]:       9174 :         LOOP_OVER_GIVEN_CHILDREN(i, packet_children)
     989                 :          0 :                 (*i)->NextPacket(len, data, is_orig, data_seq, ip, caplen);
     990                 :            : 
     991                 :       9174 :         return need_contents;
     992                 :            :         }
     993                 :            : 
     994                 :      17976 : void TCP_Analyzer::CheckRecording(int need_contents, TCP_Flags flags)
     995                 :            :         {
     996 [ +  + ][ +  - ]:      17976 :         bool record_current_content = need_contents || Conn()->RecordContents();
     997                 :            :         bool record_current_packet =
     998                 :            :                 Conn()->RecordPackets() ||
     999 [ -  + ][ #  # ]:      17976 :                 flags.SYN() || flags.FIN() || flags.RST();
         [ #  # ][ #  # ]
    1000                 :            : 
    1001                 :      17976 :         Conn()->SetRecordCurrentContent(record_current_content);
    1002                 :      17976 :         Conn()->SetRecordCurrentPacket(record_current_packet);
    1003                 :      17976 :         }
    1004                 :            : 
    1005                 :      17976 : void TCP_Analyzer::CheckPIA_FirstPacket(int is_orig, const IP_Hdr* ip)
    1006                 :            :         {
    1007 [ +  + ][ +  + ]:      17976 :         if ( is_orig && ! (first_packet_seen & ORIG) )
    1008                 :            :                 {
    1009                 :        842 :                 PIA_TCP* pia = static_cast<PIA_TCP*>(Conn()->GetPrimaryPIA());
    1010         [ +  - ]:        842 :                 if ( pia )
    1011                 :        842 :                         pia->FirstPacket(is_orig, ip);
    1012                 :        842 :                 first_packet_seen |= ORIG;
    1013                 :            :                 }
    1014                 :            : 
    1015 [ +  + ][ +  + ]:      17976 :         if ( ! is_orig && ! (first_packet_seen & RESP) )
    1016                 :            :                 {
    1017                 :        880 :                 PIA_TCP* pia = static_cast<PIA_TCP*>(Conn()->GetPrimaryPIA());
    1018         [ +  - ]:        880 :                 if ( pia )
    1019                 :        880 :                         pia->FirstPacket(is_orig, ip);
    1020                 :        880 :                 first_packet_seen |= RESP;
    1021                 :            :                 }
    1022                 :      17976 :         }
    1023                 :            : 
    1024                 :            : void TCP_Analyzer::DeliverPacket(int len, const u_char* data, bool is_orig,
    1025                 :      17976 :                                         int seq, const IP_Hdr* ip, int caplen)
    1026                 :            :         {
    1027                 :      17976 :         TransportLayerAnalyzer::DeliverPacket(len, data, orig, seq, ip, caplen);
    1028                 :            : 
    1029                 :      17976 :         const struct tcphdr* tp = ExtractTCP_Header(data, len, caplen);
    1030         [ -  + ]:      17976 :         if ( ! tp )
    1031                 :          0 :                 return;
    1032                 :            : 
    1033                 :            :         // We need the min() here because Ethernet frame padding can lead to
    1034                 :            :         // caplen > len.
    1035         [ -  + ]:      17976 :         if ( packet_contents )
    1036                 :          0 :                 PacketContents(data, min(len, caplen));
    1037                 :            : 
    1038         [ +  + ]:      17976 :         TCP_Endpoint* endpoint = is_orig ? orig : resp;
    1039                 :      17976 :         TCP_Endpoint* peer = endpoint->peer;
    1040                 :            : 
    1041         [ -  + ]:      17976 :         if ( ! ValidateChecksum(tp, endpoint, len, caplen) )
    1042                 :          0 :                 return;
    1043                 :            : 
    1044                 :      17976 :         TCP_Flags flags(tp);
    1045                 :            : 
    1046                 :      17976 :         uint32 base_seq = ntohl(tp->th_seq);
    1047                 :      17976 :         uint32 ack_seq = ntohl(tp->th_ack);
    1048                 :            : 
    1049                 :      17976 :         CheckFlagCombos(flags, endpoint, base_seq, len, ntohs(tp->th_dport));
    1050                 :            : 
    1051                 :      17976 :         UpdateWindow(endpoint, ntohs(tp->th_win), base_seq, ack_seq, flags);
    1052                 :            : 
    1053                 :      17976 :         double t = current_timestamp;
    1054                 :            : 
    1055   [ +  +  +  + ]:      17976 :         if ( ! orig->did_close || ! resp->did_close )
    1056                 :      17490 :                 Conn()->SetLastTime(t);
    1057                 :            : 
    1058                 :      17976 :         const uint32* orig_addr = Conn()->OrigAddr();
    1059                 :      17976 :         const uint32* resp_addr = Conn()->RespAddr();
    1060                 :            : 
    1061                 :      17976 :         uint32 tcp_hdr_len = data - (const u_char*) tp;
    1062                 :            : 
    1063                 :      17976 :         int seq_len = len;      // length in terms of sequence space
    1064                 :            : 
    1065         [ -  + ]:      17976 :         if ( ! ProcessFlags(t, ip, tp, tcp_hdr_len, len, seq_len,
    1066                 :            :                                 endpoint, peer, base_seq, ack_seq,
    1067                 :            :                                 orig_addr, is_orig, flags) )
    1068                 :          0 :                 return;
    1069                 :            : 
    1070                 :      17976 :         uint32 last_seq = base_seq + seq_len;
    1071                 :            : 
    1072         [ +  + ]:      17976 :         if ( endpoint->state == TCP_ENDPOINT_INACTIVE )
    1073                 :            :                 TransitionFromInactive(t, endpoint, base_seq, last_seq,
    1074                 :       1732 :                                         flags.SYN());
    1075                 :            : 
    1076                 :      17976 :         int delta_last = UpdateLastSeq(endpoint, last_seq, flags);
    1077                 :            : 
    1078                 :      17976 :         endpoint->last_time = t;
    1079                 :            : 
    1080                 :            :         int do_close;
    1081                 :            :         int gen_event;
    1082                 :            :         UpdateStateMachine(t, endpoint, peer, base_seq, ack_seq, last_seq,
    1083                 :            :                                 len, delta_last, is_orig, flags,
    1084                 :      17976 :                                 do_close, gen_event);
    1085                 :            : 
    1086         [ -  + ]:      17976 :         if ( tcp_packet )
    1087                 :            :                 GeneratePacketEvent(endpoint, peer, base_seq, ack_seq,
    1088                 :          0 :                                         data, len, caplen, is_orig, flags);
    1089                 :            : 
    1090 [ -  + ][ #  # ]:      17976 :         if ( tcp_option && tcp_hdr_len > sizeof(*tp) &&
         [ #  # ][ -  + ]
    1091                 :            :              tcp_hdr_len <= uint32(caplen) )
    1092                 :          0 :                 ParseTCPOptions(tp, TCPOptionEvent, this, is_orig, 0);
    1093                 :            : 
    1094 [ -  + ][ #  # ]:      17976 :         if ( TraceRewriter() && current_hdr )
                 [ -  + ]
    1095                 :            :                 {
    1096                 :          0 :                 TCP_Rewriter* r = (TCP_Rewriter*) TraceRewriter();
    1097                 :            :                 r->NextPacket(is_orig, t, current_hdr, current_pkt,
    1098                 :          0 :                                 current_hdr_size, ip->IP4_Hdr(), tp);
    1099                 :            :                 }
    1100                 :            : 
    1101 [ -  + ][ #  # ]:      17976 :         if ( src_pkt_writer && current_hdr )
    1102                 :          0 :                 src_pkt_writer->NextPacket(current_hdr, current_pkt);
    1103                 :            : 
    1104                 :            :         if ( DEBUG_tcp_data_sent )
    1105                 :            :                 {
    1106                 :            :                 DEBUG_MSG("%.6f before DataSent: len=%d caplen=%d skip=%d\n",
    1107                 :            :                           network_time, len, caplen, Skipping());
    1108                 :            :                 }
    1109                 :            : 
    1110                 :      17976 :         int need_contents = 0;
    1111 [ +  + ][ -  + ]:      17976 :         if ( len > 0 && (caplen >= len || packet_children.size()) &&
         [ #  # ][ +  + ]
         [ +  - ][ +  + ]
    1112                 :            :              ! flags.RST() && ! Skipping() )
    1113                 :            :                 need_contents = DeliverData(t, data, len, caplen, ip, tp,
    1114                 :            :                                                 endpoint, base_seq,
    1115                 :       9174 :                                                 is_orig, flags);
    1116                 :            : 
    1117                 :      17976 :         endpoint->CheckEOF();
    1118                 :            : 
    1119         [ +  + ]:      17976 :         if ( do_close )
    1120                 :            :                 {
    1121                 :            :                 // We need to postpone doing this until after we process
    1122                 :            :                 // DataSent, so we don't generate a connection_finished event
    1123                 :            :                 // until after data perhaps included with the FIN is processed.
    1124                 :       1047 :                 ConnectionClosed(endpoint, peer, gen_event);
    1125                 :            :                 }
    1126                 :            : 
    1127                 :      17976 :         CheckRecording(need_contents, flags);
    1128                 :            : 
    1129         [ -  + ]:      17976 :         if ( ! reassembling )
    1130                 :            :                 ForwardPacket(len, data, is_orig,
    1131                 :          0 :                                 base_seq - endpoint->StartSeq(), ip, caplen);
    1132                 :            : 
    1133                 :      17976 :         CheckPIA_FirstPacket(is_orig, ip);
    1134                 :            :         }
    1135                 :            : 
    1136                 :          0 : void TCP_Analyzer::DeliverStream(int len, const u_char* data, bool orig)
    1137                 :            :         {
    1138                 :          0 :         Analyzer::DeliverStream(len, data, orig);
    1139                 :          0 :         }
    1140                 :            : 
    1141                 :          0 : void TCP_Analyzer::Undelivered(int seq, int len, bool is_orig)
    1142                 :            :         {
    1143                 :          0 :         Analyzer::Undelivered(seq, len, orig);
    1144                 :          0 :         }
    1145                 :            : 
    1146                 :          0 : void TCP_Analyzer::FlipRoles()
    1147                 :            :         {
    1148                 :          0 :         Analyzer::FlipRoles();
    1149                 :            : 
    1150                 :          0 :         sessions->tcp_stats.FlipState(orig->state, resp->state);
    1151                 :          0 :         TCP_Endpoint* tmp_ep = resp;
    1152                 :          0 :         resp = orig;
    1153                 :          0 :         orig = tmp_ep;
    1154                 :          0 :         orig->is_orig = !orig->is_orig;
    1155                 :          0 :         resp->is_orig = !resp->is_orig;
    1156                 :          0 :         }
    1157                 :            : 
    1158                 :      31290 : void TCP_Analyzer::UpdateEndpointVal(RecordVal* endp, int is_orig)
    1159                 :            :         {
    1160         [ +  + ]:      31290 :         TCP_Endpoint* s = is_orig ? orig : resp;
    1161                 :      31290 :         endp->Assign(0, new Val(s->Size(), TYPE_COUNT));
    1162                 :      31290 :         endp->Assign(1, new Val(int(s->state), TYPE_COUNT));
    1163                 :      31290 :         }
    1164                 :            : 
    1165                 :            : Val* TCP_Analyzer::BuildSYNPacketVal(int is_orig, const IP_Hdr* ip,
    1166                 :       1042 :                                         const struct tcphdr* tcp)
    1167                 :            :         {
    1168                 :       1042 :         int winscale = -1;
    1169                 :       1042 :         int MSS = 0;
    1170                 :       1042 :         int SACK = 0;
    1171                 :            : 
    1172                 :            :         // Parse TCP options.
    1173                 :       1042 :         u_char* options = (u_char*) tcp + sizeof(struct tcphdr);
    1174                 :       1042 :         u_char* opt_end = (u_char*) tcp + tcp->th_off * 4;
    1175                 :            : 
    1176         [ +  + ]:       4051 :         while ( options < opt_end )
    1177                 :            :                 {
    1178                 :       3080 :                 unsigned int opt = options[0];
    1179                 :            : 
    1180         [ +  + ]:       3080 :                 if ( opt == TCPOPT_EOL )
    1181                 :            :                         // All done - could flag if more junk left over ....
    1182                 :         71 :                         break;
    1183                 :            : 
    1184         [ +  + ]:       3009 :                 if ( opt == TCPOPT_NOP )
    1185                 :            :                         {
    1186                 :       1140 :                         ++options;
    1187                 :       1140 :                         continue;
    1188                 :            :                         }
    1189                 :            : 
    1190         [ -  + ]:       1869 :                 if ( options + 1 >= opt_end )
    1191                 :            :                         // We've run off the end, no room for the length.
    1192                 :          0 :                         break;
    1193                 :            : 
    1194                 :       1869 :                 unsigned int opt_len = options[1];
    1195                 :            : 
    1196         [ -  + ]:       1869 :                 if ( options + opt_len > opt_end )
    1197                 :            :                         // No room for rest of option.
    1198                 :          0 :                         break;
    1199                 :            : 
    1200         [ -  + ]:       1869 :                 if ( opt_len == 0 )
    1201                 :            :                         // Trashed length field.
    1202                 :          0 :                         break;
    1203                 :            : 
    1204   [ +  +  +  + ]:       1869 :                 switch ( opt ) {
    1205                 :            :                 case TCPOPT_SACK_PERMITTED:
    1206                 :        480 :                         SACK = 1;
    1207                 :        480 :                         break;
    1208                 :            : 
    1209                 :            :                 case TCPOPT_MAXSEG:
    1210         [ -  + ]:        518 :                         if ( opt_len < 4 )
    1211                 :          0 :                                 break;  // bad length
    1212                 :            : 
    1213                 :        518 :                         MSS = (options[2] << 8) | options[3];
    1214                 :        518 :                         break;
    1215                 :            : 
    1216                 :            :                 case 3: // TCPOPT_WSCALE
    1217         [ -  + ]:        492 :                         if ( opt_len < 3 )
    1218                 :          0 :                                 break;  // bad length
    1219                 :            : 
    1220                 :        492 :                         winscale = options[2];
    1221                 :            :                         break;
    1222                 :            : 
    1223                 :            :                 default:        // just skip over
    1224                 :            :                         break;
    1225                 :            :                 }
    1226                 :            : 
    1227                 :       1869 :                 options += opt_len;
    1228                 :            :                 }
    1229                 :            : 
    1230                 :       1042 :         RecordVal* v = new RecordVal(SYN_packet);
    1231                 :            : 
    1232                 :       1042 :         v->Assign(0, new Val(is_orig, TYPE_BOOL));
    1233                 :       1042 :         v->Assign(1, new Val(int(ip->DF()), TYPE_BOOL));
    1234                 :       1042 :         v->Assign(2, new Val(int(ip->TTL()), TYPE_INT));
    1235                 :       1042 :         v->Assign(3, new Val((ip->TotalLen()), TYPE_INT));
    1236                 :       1042 :         v->Assign(4, new Val(ntohs(tcp->th_win), TYPE_INT));
    1237                 :       1042 :         v->Assign(5, new Val(winscale, TYPE_INT));
    1238                 :       1042 :         v->Assign(6, new Val(MSS, TYPE_INT));
    1239                 :       1042 :         v->Assign(7, new Val(SACK, TYPE_BOOL));
    1240                 :            : 
    1241                 :       1042 :         return v;
    1242                 :            :         }
    1243                 :            : 
    1244                 :            : RecordVal* TCP_Analyzer::BuildOSVal(int is_orig, const IP_Hdr* ip,
    1245                 :          0 :                         const struct tcphdr* tcp, uint32 tcp_hdr_len)
    1246                 :            :         {
    1247         [ #  # ]:          0 :         if ( ! is_orig )
    1248                 :            :                 // Later we might use SYN-ACK fingerprinting here.
    1249                 :          0 :                 return 0;
    1250                 :            : 
    1251                 :            :         // Passive OS fingerprinting wants to know a lot about IP and TCP
    1252                 :            :         // options: how many options there are, and in which order.
    1253                 :          0 :         int winscale = 0;
    1254                 :          0 :         int MSS = 0;
    1255                 :          0 :         int optcount = 0;
    1256                 :          0 :         uint32 quirks = 0;
    1257                 :          0 :         uint32 tstamp = 0;
    1258                 :            :         uint8 op[MAXOPT];
    1259                 :            : 
    1260         [ #  # ]:          0 :         if ( ip->HdrLen() > 20 )
    1261                 :          0 :                 quirks |= QUIRK_IPOPT;
    1262                 :            : 
    1263         [ #  # ]:          0 :         if ( ip->IP_ID() == 0 )
    1264                 :          0 :                 quirks |= QUIRK_ZEROID;
    1265                 :            : 
    1266         [ #  # ]:          0 :         if ( tcp->th_seq == 0 )
    1267                 :          0 :                 quirks |= QUIRK_SEQ0;
    1268                 :            : 
    1269         [ #  # ]:          0 :         if ( tcp->th_seq == tcp->th_ack )
    1270                 :          0 :                 quirks |= QUIRK_SEQEQ;
    1271                 :            : 
    1272         [ #  # ]:          0 :         if ( tcp->th_flags & ~(TH_SYN|TH_ACK|TH_RST|TH_ECE|TH_CWR) )
    1273                 :          0 :                 quirks |= QUIRK_FLAGS;
    1274                 :            : 
    1275         [ #  # ]:          0 :         if ( ip->TotalLen() - ip->HdrLen() - tcp_hdr_len > 0 )
    1276                 :          0 :                 quirks |= QUIRK_DATA;   // SYN with data
    1277                 :            : 
    1278         [ #  # ]:          0 :         if ( tcp->th_ack )
    1279                 :          0 :                 quirks |= QUIRK_ACK;
    1280         [ #  # ]:          0 :         if ( tcp->th_urp )
    1281                 :          0 :                 quirks |= QUIRK_URG;
    1282         [ #  # ]:          0 :         if ( tcp->th_x2 )
    1283                 :          0 :                 quirks |= QUIRK_X2;
    1284                 :            : 
    1285                 :            :         // Parse TCP options.
    1286                 :          0 :         u_char* options = (u_char*) tcp + sizeof(struct tcphdr);
    1287                 :          0 :         u_char* opt_end = (u_char*) tcp + tcp_hdr_len;
    1288                 :            : 
    1289         [ #  # ]:          0 :         while ( options < opt_end )
    1290                 :            :                 {
    1291                 :          0 :                 unsigned int opt = options[0];
    1292                 :            : 
    1293         [ #  # ]:          0 :                 if ( opt == TCPOPT_EOL )
    1294                 :            :                         {
    1295                 :          0 :                         op[optcount++] = TCPOPT_EOL;
    1296         [ #  # ]:          0 :                         if ( ++options < opt_end )
    1297                 :          0 :                                 quirks |= QUIRK_PAST;
    1298                 :            : 
    1299                 :            :                         // All done - could flag if more junk left over ....
    1300                 :          0 :                         break;
    1301                 :            :                         }
    1302                 :            : 
    1303         [ #  # ]:          0 :                 if ( opt == TCPOPT_NOP )
    1304                 :            :                         {
    1305                 :          0 :                         op[optcount++] = TCPOPT_NOP;
    1306                 :          0 :                         ++options;
    1307                 :          0 :                         continue;
    1308                 :            :                         }
    1309                 :            : 
    1310         [ #  # ]:          0 :                 if ( options + 1 >= opt_end )
    1311                 :            :                         {
    1312                 :            :                         // We've run off the end, no room for the length.
    1313                 :          0 :                         quirks |= QUIRK_BROKEN;
    1314                 :          0 :                         break;
    1315                 :            :                         }
    1316                 :            : 
    1317                 :          0 :                 unsigned int opt_len = options[1];
    1318                 :            : 
    1319         [ #  # ]:          0 :                 if ( options + opt_len > opt_end )
    1320                 :            :                         {
    1321                 :            :                         // No room for rest of the options.
    1322                 :          0 :                         quirks |= QUIRK_BROKEN;
    1323                 :          0 :                         break;
    1324                 :            :                         }
    1325                 :            : 
    1326         [ #  # ]:          0 :                 if ( opt_len == 0 )
    1327                 :            :                         // Trashed length field.
    1328                 :          0 :                         break;
    1329                 :            : 
    1330   [ #  #  #  #  :          0 :                 switch ( opt ) {
                      # ]
    1331                 :            :                 case TCPOPT_SACK_PERMITTED:
    1332                 :            :                         // SACKOK LEN
    1333                 :          0 :                         op[optcount] = TCPOPT_SACK_PERMITTED;
    1334                 :          0 :                         break;
    1335                 :            : 
    1336                 :            :                 case TCPOPT_MAXSEG:
    1337                 :            :                         // MSS LEN D0 D1
    1338         [ #  # ]:          0 :                         if ( opt_len < 4 )
    1339                 :          0 :                                 break;  // bad length
    1340                 :            : 
    1341                 :          0 :                         op[optcount] = TCPOPT_MAXSEG;
    1342                 :          0 :                         MSS = (options[2] << 8) | options[3];
    1343                 :          0 :                         break;
    1344                 :            : 
    1345                 :            :                 case TCPOPT_WINDOW:
    1346                 :            :                         // WSCALE LEN D0
    1347         [ #  # ]:          0 :                         if ( opt_len < 3 )
    1348                 :          0 :                                 break;  // bad length
    1349                 :            : 
    1350                 :          0 :                         op[optcount] = TCPOPT_WINDOW;
    1351                 :          0 :                         winscale = options[2];
    1352                 :          0 :                         break;
    1353                 :            : 
    1354                 :            :                 case TCPOPT_TIMESTAMP:
    1355                 :            :                         // TSTAMP LEN T0 T1 T2 T3 A0 A1 A2 A3
    1356         [ #  # ]:          0 :                         if ( opt_len < 10 )
    1357                 :          0 :                                 break;  // bad length
    1358                 :            : 
    1359                 :          0 :                         op[optcount] = TCPOPT_TIMESTAMP;
    1360                 :            : 
    1361                 :          0 :                         tstamp = ntohl(extract_uint32(options + 2));
    1362                 :            : 
    1363         [ #  # ]:          0 :                         if ( extract_uint32(options + 6) )
    1364                 :          0 :                                 quirks |= QUIRK_T2;
    1365                 :          0 :                         break;
    1366                 :            : 
    1367                 :            :                 default:        // just skip over
    1368                 :          0 :                         op[optcount]=opt;
    1369                 :            :                         break;
    1370                 :            :                 }
    1371                 :            : 
    1372         [ #  # ]:          0 :                 if ( optcount < MAXOPT - 1 )
    1373                 :          0 :                         ++optcount;
    1374                 :            :                 else
    1375                 :          0 :                         quirks |= QUIRK_BROKEN;
    1376                 :            : 
    1377                 :          0 :                 options += opt_len;
    1378                 :            :                 }
    1379                 :            : 
    1380                 :            :         struct os_type os_from_print;
    1381                 :            :         int id = sessions->Get_OS_From_SYN(&os_from_print,
    1382                 :            :                         uint16(ip->TotalLen()),
    1383                 :            :                         uint8(ip->DF()), uint8(ip->TTL()),
    1384                 :            :                         uint16(ntohs(tcp->th_win)),
    1385                 :            :                         uint8(optcount), op,
    1386                 :            :                         uint16(MSS), uint8(winscale),
    1387                 :            :                         tstamp, quirks,
    1388                 :          0 :                         uint8(tcp->th_flags & (TH_ECE|TH_CWR)));
    1389                 :            : 
    1390         [ #  # ]:          0 :         if ( sessions->CompareWithPreviousOSMatch(ip->SrcAddr4(), id) )
    1391                 :            :                 {
    1392                 :          0 :                 RecordVal* os = new RecordVal(OS_version);
    1393                 :            : 
    1394                 :          0 :                 os->Assign(0, new StringVal(os_from_print.os));
    1395                 :            : 
    1396         [ #  # ]:          0 :                 if ( os_from_print.desc )
    1397                 :          0 :                         os->Assign(1, new StringVal(os_from_print.desc));
    1398                 :            :                 else
    1399                 :          0 :                         os->Assign(1, new StringVal(""));
    1400                 :            : 
    1401                 :          0 :                 os->Assign(2, new Val(os_from_print.dist, TYPE_COUNT));
    1402                 :          0 :                 os->Assign(3, new EnumVal(os_from_print.match, OS_version_inference));
    1403                 :            : 
    1404                 :          0 :                 return os;
    1405                 :            :                 }
    1406                 :            : 
    1407                 :          0 :         return 0;
    1408                 :            :         }
    1409                 :            : 
    1410                 :            : int TCP_Analyzer::ParseTCPOptions(const struct tcphdr* tcp,
    1411                 :            :                                         proc_tcp_option_t proc,
    1412                 :            :                                         TCP_Analyzer* analyzer,
    1413                 :       1104 :                                         bool is_orig, void* cookie)
    1414                 :            :         {
    1415                 :            :         // Parse TCP options.
    1416                 :       1104 :         const u_char* options = (const u_char*) tcp + sizeof(struct tcphdr);
    1417                 :       1104 :         const u_char* opt_end = (const u_char*) tcp + tcp->th_off * 4;
    1418                 :            : 
    1419         [ +  + ]:       6577 :         while ( options < opt_end )
    1420                 :            :                 {
    1421                 :       5910 :                 unsigned int opt = options[0];
    1422                 :            : 
    1423                 :            :                 unsigned int opt_len;
    1424                 :            : 
    1425         [ +  + ]:       5910 :                 if ( opt < 2 )
    1426                 :       2979 :                         opt_len = 1;
    1427                 :            : 
    1428         [ -  + ]:       2931 :                 else if ( options + 1 >= opt_end )
    1429                 :            :                         // We've run off the end, no room for the length.
    1430                 :          0 :                         return -1;
    1431                 :            : 
    1432                 :            :                 else
    1433                 :       2931 :                         opt_len = options[1];
    1434                 :            : 
    1435         [ -  + ]:       5910 :                 if ( opt_len == 0 )
    1436                 :          0 :                         return -1;      // trashed length field
    1437                 :            : 
    1438         [ -  + ]:       5910 :                 if ( options + opt_len > opt_end )
    1439                 :            :                         // No room for rest of option.
    1440                 :          0 :                         return -1;
    1441                 :            : 
    1442         [ -  + ]:       5910 :                 if ( (*proc)(opt, opt_len, options, analyzer, is_orig, cookie) == -1 )
    1443                 :          0 :                         return -1;
    1444                 :            : 
    1445                 :       5910 :                 options += opt_len;
    1446                 :            : 
    1447         [ +  + ]:       5910 :                 if ( opt == TCPOPT_EOL )
    1448                 :            :                         // All done - could flag if more junk left over ....
    1449                 :        437 :                         break;
    1450                 :            :                 }
    1451                 :            : 
    1452                 :       1104 :         return 0;
    1453                 :            :         }
    1454                 :            : 
    1455                 :            : int TCP_Analyzer::TCPOptionEvent(unsigned int opt,
    1456                 :            :                                         unsigned int optlen,
    1457                 :            :                                         const u_char* /* option */,
    1458                 :            :                                         TCP_Analyzer* analyzer,
    1459                 :          0 :                                         bool is_orig, void* cookie)
    1460                 :            :         {
    1461         [ #  # ]:          0 :         if ( tcp_option )
    1462                 :            :                 {
    1463                 :          0 :                 val_list* vl = new val_list();
    1464                 :            : 
    1465                 :          0 :                 vl->append(analyzer->BuildConnVal());
    1466                 :          0 :                 vl->append(new Val(is_orig, TYPE_BOOL));
    1467                 :          0 :                 vl->append(new Val(opt, TYPE_COUNT));
    1468                 :          0 :                 vl->append(new Val(optlen, TYPE_COUNT));
    1469                 :            : 
    1470                 :          0 :                 analyzer->ConnectionEvent(tcp_option, vl);
    1471                 :            :                 }
    1472                 :            : 
    1473                 :          0 :         return 0;
    1474                 :            :         }
    1475                 :            : 
    1476                 :        295 : void TCP_Analyzer::AttemptTimer(double /* t */)
    1477                 :            :         {
    1478         [ -  + ]:        295 :         if ( ! is_active )
    1479                 :          0 :                 return;
    1480                 :            : 
    1481 [ +  + ][ +  + ]:        295 :         if ( (orig->state == TCP_ENDPOINT_SYN_SENT ||
                 [ +  + ]
    1482                 :            :               orig->state == TCP_ENDPOINT_SYN_ACK_SENT) &&
    1483                 :            :              resp->state == TCP_ENDPOINT_INACTIVE )
    1484                 :            :                 {
    1485                 :          4 :                 Event(connection_attempt);
    1486                 :          4 :                 is_active = 0;
    1487                 :            : 
    1488                 :            :                 // All done with this connection.
    1489                 :        295 :                 sessions->Remove(Conn());
    1490                 :            :                 }
    1491                 :            :         }
    1492                 :            : 
    1493                 :          4 : void TCP_Analyzer::PartialCloseTimer(double /* t */)
    1494                 :            :         {
    1495         [ -  + ]:          4 :         if ( ! is_active )
    1496                 :          0 :                 return;
    1497                 :            : 
    1498 [ +  - ][ +  - ]:          4 :         if ( orig->state != TCP_ENDPOINT_INACTIVE &&
         [ -  + ][ #  # ]
    1499                 :            :              resp->state != TCP_ENDPOINT_INACTIVE &&
    1500                 :            :              (! orig->did_close || ! resp->did_close) )
    1501                 :            :                 {
    1502 [ +  - ][ -  + ]:          4 :                 if ( orig->state == TCP_ENDPOINT_RESET ||
    1503                 :            :                      resp->state == TCP_ENDPOINT_RESET )
    1504                 :            :                         // Presumably the RST is what caused the partial
    1505                 :            :                         // close.  Don't report it.
    1506                 :          0 :                         return;
    1507                 :            : 
    1508                 :          4 :                 Event(connection_partial_close);
    1509                 :          4 :                 sessions->Remove(Conn());
    1510                 :            :                 }
    1511                 :            :         }
    1512                 :            : 
    1513                 :      15596 : void TCP_Analyzer::ExpireTimer(double t)
    1514                 :            :         {
    1515         [ +  + ]:      15596 :         if ( ! is_active )
    1516                 :          8 :                 return;
    1517                 :            : 
    1518         [ +  + ]:      15588 :         if ( Conn()->LastTime() + tcp_connection_linger < t )
    1519                 :            :                 {
    1520 [ +  + ][ +  + ]:      15022 :                 if ( orig->did_close || resp->did_close )
    1521                 :            :                         {
    1522                 :            :                         // No activity for tcp_connection_linger seconds, and
    1523                 :            :                         // at least one side has closed.  See whether
    1524                 :            :                         // connection has likely terminated.
    1525 [ +  + ][ +  - ]:       6763 :                         if ( (orig->did_close && resp->did_close) ||
         [ +  - ][ +  + ]
         [ +  - ][ -  + ]
    1526                 :            :                              (orig->state == TCP_ENDPOINT_RESET ||
    1527                 :            :                               resp->state == TCP_ENDPOINT_RESET) ||
    1528                 :            :                              (orig->state == TCP_ENDPOINT_INACTIVE ||
    1529                 :            :                               resp->state == TCP_ENDPOINT_INACTIVE) )
    1530                 :            :                                 {
    1531                 :            :                                 // Either both closed, or one RST,
    1532                 :            :                                 // or half-closed.
    1533                 :            : 
    1534                 :            :                                 // The Timer has Ref()'d us and won't Unref()
    1535                 :            :                                 // us until we return, so it's safe to have
    1536                 :            :                                 // the session remove and Unref() us here.
    1537                 :          2 :                                 Event(connection_timeout);
    1538                 :          2 :                                 is_active = 0;
    1539                 :          2 :                                 sessions->Remove(Conn());
    1540                 :          2 :                                 return;
    1541                 :            :                                 }
    1542                 :            :                         }
    1543                 :            : 
    1544         [ +  + ]:      15020 :                 if ( resp->state == TCP_ENDPOINT_INACTIVE )
    1545                 :            :                         {
    1546 [ +  + ][ -  + ]:        474 :                         if ( (orig->state == TCP_ENDPOINT_SYN_SENT ||
    1547                 :            :                               orig->state == TCP_ENDPOINT_SYN_ACK_SENT) )
    1548                 :            :                                 {
    1549         [ -  + ]:          3 :                                 if ( ! connection_attempt )
    1550                 :            :                                         {
    1551                 :            :                                         // Time out the connection attempt,
    1552                 :            :                                         // since the AttemptTimer isn't going
    1553                 :            :                                         // to do it for us, and we don't want
    1554                 :            :                                         // to clog the data structures with
    1555                 :            :                                         // old, failed attempts.
    1556                 :          0 :                                         Event(connection_timeout);
    1557                 :          0 :                                         is_active = 0;
    1558                 :          0 :                                         sessions->Remove(Conn());
    1559                 :          0 :                                         return;
    1560                 :            :                                         }
    1561                 :            :                                 }
    1562                 :            : 
    1563         [ -  + ]:        468 :                         else if ( orig->state == TCP_ENDPOINT_INACTIVE )
    1564                 :            :                                 {
    1565                 :            :                                 // Nothing ever happened on this connection.
    1566                 :            :                                 // This can occur when we see a trashed
    1567                 :            :                                 // packet - it's discarded by NextPacket
    1568                 :            :                                 // before setting up an attempt timer,
    1569                 :            :                                 // so we need to clean it up here.
    1570                 :          0 :                                 Event(connection_timeout);
    1571                 :          0 :                                 sessions->Remove(Conn());
    1572                 :          0 :                                 return;
    1573                 :            :                                 }
    1574                 :            :                         }
    1575                 :            :                 }
    1576                 :            : 
    1577                 :            :         // Connection still active, so reschedule timer.
    1578                 :            :         // ### if PQ_Element's were BroObj's, could just Ref the timer
    1579                 :            :         // and adjust its value here, instead of creating a new timer.
    1580                 :      15596 :         ADD_ANALYZER_TIMER(&TCP_Analyzer::ExpireTimer, t + tcp_session_timer,
    1581                 :            :                         0, TIMER_TCP_EXPIRE);
    1582                 :            :         }
    1583                 :            : 
    1584                 :         24 : void TCP_Analyzer::ResetTimer(double /* t */)
    1585                 :            :         {
    1586         [ -  + ]:         24 :         if ( ! is_active )
    1587                 :          0 :                 return;
    1588                 :            : 
    1589         [ +  - ]:         24 :         if ( ! BothClosed() )
    1590                 :         24 :                 ConnectionReset();
    1591                 :            : 
    1592                 :         24 :         sessions->Remove(Conn());
    1593                 :            :         }
    1594                 :            : 
    1595                 :          0 : void TCP_Analyzer::DeleteTimer(double /* t */)
    1596                 :            :         {
    1597                 :          0 :         sessions->Remove(Conn());
    1598                 :          0 :         }
    1599                 :            : 
    1600                 :            : 
    1601                 :            : // The following need to be consistent with bro.init.
    1602                 :            : #define CONTENTS_NONE 0
    1603                 :            : #define CONTENTS_ORIG 1
    1604                 :            : #define CONTENTS_RESP 2
    1605                 :            : #define CONTENTS_BOTH 3
    1606                 :            : 
    1607                 :          0 : void TCP_Analyzer::SetContentsFile(unsigned int direction, BroFile* f)
    1608                 :            :         {
    1609         [ #  # ]:          0 :         if ( direction == CONTENTS_NONE )
    1610                 :            :                 {
    1611                 :          0 :                 orig->SetContentsFile(0);
    1612                 :          0 :                 resp->SetContentsFile(0);
    1613                 :            :                 }
    1614                 :            : 
    1615                 :            :         else
    1616                 :            :                 {
    1617 [ #  # ][ #  # ]:          0 :                 if ( direction == CONTENTS_ORIG || direction == CONTENTS_BOTH )
    1618                 :          0 :                         orig->SetContentsFile(f);
    1619 [ #  # ][ #  # ]:          0 :                 if ( direction == CONTENTS_RESP || direction == CONTENTS_BOTH )
    1620                 :          0 :                         resp->SetContentsFile(f);
    1621                 :            :                 }
    1622                 :          0 :         }
    1623                 :            : 
    1624                 :          0 : BroFile* TCP_Analyzer::GetContentsFile(unsigned int direction) const
    1625                 :            :         {
    1626   [ #  #  #  #  :          0 :         switch ( direction ) {
                      # ]
    1627                 :            :         case CONTENTS_NONE:
    1628                 :          0 :                 return 0;
    1629                 :            : 
    1630                 :            :         case CONTENTS_ORIG:
    1631                 :          0 :                 return orig->GetContentsFile();
    1632                 :            : 
    1633                 :            :         case CONTENTS_RESP:
    1634                 :          0 :                 return resp->GetContentsFile();
    1635                 :            : 
    1636                 :            :         case CONTENTS_BOTH:
    1637         [ #  # ]:          0 :                 if ( orig->GetContentsFile() != resp->GetContentsFile())
    1638                 :            :                         // This is an "error".
    1639                 :          0 :                         return 0;
    1640                 :            :                 else
    1641                 :          0 :                         return orig->GetContentsFile();
    1642                 :            : 
    1643                 :            :         default:
    1644                 :            :                 break;
    1645                 :            :         }
    1646                 :          0 :         internal_error("inconsistency in TCP_Analyzer::GetContentsFile");
    1647                 :            :         return 0;
    1648                 :            :         }
    1649                 :            : 
    1650                 :            : void TCP_Analyzer::ConnectionClosed(TCP_Endpoint* endpoint, TCP_Endpoint* peer,
    1651                 :       1093 :                                         int gen_event)
    1652                 :            :         {
    1653                 :       1093 :         const analyzer_list& children(GetChildren());
    1654         [ +  + ]:       2929 :         LOOP_OVER_CONST_CHILDREN(i)
    1655                 :            :                 // Using this type of cast here is nasty (will crash if
    1656                 :            :                 // we inadvertantly have a child analyzer that's not a
    1657                 :            :                 // TCP_ApplicationAnalyzer), but we have to ...
    1658                 :            :                 static_cast<TCP_ApplicationAnalyzer*>
    1659                 :       1836 :                         (*i)->ConnectionClosed(endpoint, peer, gen_event);
    1660                 :            : 
    1661         [ +  + ]:       1093 :         if ( DataPending(endpoint) )
    1662                 :            :                 {
    1663                 :            :                 // Don't close out the connection yet, there's still data to
    1664                 :            :                 // deliver.
    1665                 :         77 :                 close_deferred = 1;
    1666         [ +  + ]:         77 :                 if ( ! deferred_gen_event )
    1667                 :         69 :                         deferred_gen_event = gen_event;
    1668                 :         77 :                 return;
    1669                 :            :                 }
    1670                 :            : 
    1671                 :       1016 :         close_deferred = 0;
    1672                 :            : 
    1673         [ +  + ]:       1016 :         if ( endpoint->did_close )
    1674                 :         13 :                 return; // nothing new to report
    1675                 :            : 
    1676                 :       1003 :         endpoint->did_close = 1;
    1677                 :            : 
    1678                 :            :         int close_complete =
    1679                 :            :                 endpoint->state == TCP_ENDPOINT_RESET ||
    1680                 :            :                                         peer->did_close ||
    1681 [ +  + ][ +  + ]:       1003 :                                         peer->state == TCP_ENDPOINT_INACTIVE;
                 [ +  + ]
    1682                 :            : 
    1683                 :            :         if ( DEBUG_tcp_connection_close )
    1684                 :            :                 {
    1685                 :            :                 DEBUG_MSG("%.6f close_complete=%d tcp_close_delay=%f\n",
    1686                 :            :                                 network_time, close_complete, tcp_close_delay);
    1687                 :            :                 }
    1688                 :            : 
    1689         [ +  + ]:       1003 :         if ( close_complete )
    1690                 :            :                 {
    1691 [ +  + ][ +  + ]:        570 :                 if ( endpoint->prev_state != TCP_ENDPOINT_INACTIVE ||
    1692                 :            :                      peer->state != TCP_ENDPOINT_INACTIVE )
    1693                 :            :                         {
    1694         [ +  + ]:        418 :                         if ( deferred_gen_event )
    1695                 :            :                                 {
    1696                 :         22 :                                 gen_event = 1;
    1697                 :         22 :                                 deferred_gen_event = 0; // clear flag
    1698                 :            :                                 }
    1699                 :            : 
    1700                 :            :                         // We have something interesting to report.
    1701         [ +  + ]:        418 :                         if ( gen_event )
    1702                 :            :                                 {
    1703         [ +  + ]:        395 :                                 if ( peer->state == TCP_ENDPOINT_INACTIVE )
    1704                 :         26 :                                         ConnectionFinished(1);
    1705                 :            :                                 else
    1706                 :        369 :                                         ConnectionFinished(0);
    1707                 :            :                                 }
    1708                 :            :                         }
    1709                 :            : 
    1710                 :        570 :                 CancelTimers();
    1711                 :            : 
    1712                 :            :                 // Note, even if tcp_close_delay is zero, we can't
    1713                 :            :                 // simply do:
    1714                 :            :                 //
    1715                 :            :                 //      sessions->Remove(this);
    1716                 :            :                 //
    1717                 :            :                 // here, because that would cause the object to be
    1718                 :            :                 // deleted out from under us.
    1719         [ +  - ]:        570 :                 if ( tcp_close_delay != 0.0 )
    1720                 :        570 :                         ADD_ANALYZER_TIMER(&TCP_Analyzer::ConnDeleteTimer,
    1721                 :            :                                 Conn()->LastTime() + tcp_close_delay, 0,
    1722                 :            :                                 TIMER_CONN_DELETE);
    1723                 :            :                 else
    1724                 :        570 :                         ADD_ANALYZER_TIMER(&TCP_Analyzer::DeleteTimer, Conn()->LastTime(), 0,
    1725                 :            :                                         TIMER_TCP_DELETE);
    1726                 :            :                 }
    1727                 :            : 
    1728                 :            :         else
    1729                 :            :                 { // We haven't yet seen a full close.
    1730         [ +  + ]:        433 :                 if ( endpoint->prev_state == TCP_ENDPOINT_INACTIVE )
    1731                 :            :                         { // First time we've seen anything from this side.
    1732         [ +  - ]:          8 :                         if ( connection_partial_close )
    1733                 :          8 :                                 ADD_ANALYZER_TIMER(&TCP_Analyzer::PartialCloseTimer,
    1734                 :            :                                         Conn()->LastTime() + tcp_partial_close_delay, 0,
    1735                 :            :                                         TIMER_TCP_PARTIAL_CLOSE );
    1736                 :            :                         }
    1737                 :            : 
    1738                 :            :                 else
    1739                 :            :                         {
    1740                 :            :                         // Create a timer to look for the other side closing,
    1741                 :            :                         // too.
    1742                 :       1093 :                         ADD_ANALYZER_TIMER(&TCP_Analyzer::ExpireTimer,
    1743                 :            :                                         Conn()->LastTime() + tcp_session_timer, 0,
    1744                 :            :                                         TIMER_TCP_EXPIRE);
    1745                 :            :                         }
    1746                 :            :                 }
    1747                 :            :         }
    1748                 :            : 
    1749                 :        395 : void TCP_Analyzer::ConnectionFinished(int half_finished)
    1750                 :            :         {
    1751                 :        395 :         const analyzer_list& children(GetChildren());
    1752         [ +  + ]:       1062 :         LOOP_OVER_CONST_CHILDREN(i)
    1753                 :            :                 // Again, nasty - see TCP_Analyzer::ConnectionClosed.
    1754                 :            :                 static_cast<TCP_ApplicationAnalyzer*>
    1755                 :        667 :                         (*i)->ConnectionFinished(half_finished);
    1756                 :            : 
    1757         [ +  + ]:        395 :         if ( half_finished )
    1758                 :         26 :                 Event(connection_half_finished);
    1759                 :            :         else
    1760                 :        369 :                 Event(connection_finished);
    1761                 :            : 
    1762                 :        395 :         is_active = 0;
    1763                 :        395 :         }
    1764                 :            : 
    1765                 :         50 : void TCP_Analyzer::ConnectionReset()
    1766                 :            :         {
    1767                 :         50 :         Event(connection_reset);
    1768                 :            : 
    1769                 :         50 :         const analyzer_list& children(GetChildren());
    1770         [ +  + ]:        141 :         LOOP_OVER_CONST_CHILDREN(i)
    1771                 :         91 :                 static_cast<TCP_ApplicationAnalyzer*>(*i)->ConnectionReset();
    1772                 :            : 
    1773                 :         50 :         is_active = 0;
    1774                 :         50 :         }
    1775                 :            : 
    1776                 :          0 : bool TCP_Analyzer::HadGap(bool is_orig) const
    1777                 :            :         {
    1778         [ #  # ]:          0 :         TCP_Endpoint* endp = is_orig ? orig : resp;
    1779 [ #  # ][ #  # ]:          0 :         return endp && endp->HadGap();
    1780                 :            :         }
    1781                 :            : 
    1782                 :       1139 : int TCP_Analyzer::DataPending(TCP_Endpoint* closing_endp)
    1783                 :            :         {
    1784         [ -  + ]:       1139 :         if ( Skipping() )
    1785                 :          0 :                 return 0;
    1786                 :            : 
    1787                 :       1139 :         return closing_endp->DataPending();
    1788                 :            :         }
    1789                 :            : 
    1790                 :       1010 : void TCP_Analyzer::EndpointEOF(TCP_Reassembler* endp)
    1791                 :            :         {
    1792         [ -  + ]:       1010 :         if ( connection_EOF )
    1793                 :            :                 {
    1794                 :          0 :                 val_list* vl = new val_list();
    1795                 :          0 :                 vl->append(BuildConnVal());
    1796                 :          0 :                 vl->append(new Val(endp->IsOrig(), TYPE_BOOL));
    1797                 :          0 :                 ConnectionEvent(connection_EOF, vl);
    1798                 :            :                 }
    1799                 :            : 
    1800                 :       1010 :         const analyzer_list& children(GetChildren());
    1801         [ +  + ]:       2737 :         LOOP_OVER_CONST_CHILDREN(i)
    1802                 :       1727 :                 static_cast<TCP_ApplicationAnalyzer*>(*i)->EndpointEOF(endp->IsOrig());
    1803                 :            : 
    1804                 :       1010 :         TraceRewriterEOF(endp);
    1805                 :            : 
    1806         [ +  + ]:       1010 :         if ( close_deferred )
    1807                 :            :                 {
    1808         [ -  + ]:         46 :                 if ( DataPending(endp->Endpoint()) )
    1809                 :            :                         {
    1810         [ #  # ]:          0 :                         if ( BothClosed() )
    1811                 :          0 :                                 Weird("pending_data_when_closed");
    1812                 :            : 
    1813                 :            :                         // Defer further, until the other endpoint
    1814                 :            :                         // EOF's, too.
    1815                 :            :                         }
    1816                 :            : 
    1817                 :            :                 ConnectionClosed(endp->Endpoint(), endp->Endpoint()->peer,
    1818                 :         46 :                                         deferred_gen_event);
    1819                 :         46 :                 close_deferred = 0;
    1820                 :            :                 }
    1821                 :       1010 :         }
    1822                 :            : 
    1823                 :       1010 : void TCP_Analyzer::TraceRewriterEOF(TCP_Reassembler* endp)
    1824                 :            :         {
    1825                 :       1010 :         const analyzer_list& children(GetChildren());
    1826         [ +  + ]:       2737 :         LOOP_OVER_CONST_CHILDREN(i)
    1827                 :       1727 :                 static_cast<TCP_ApplicationAnalyzer*>(*i)->TraceRewriterEOF(endp->IsOrig());
    1828                 :            : 
    1829                 :       1010 :         TCP_Rewriter* r = (TCP_Rewriter*) TraceRewriter();
    1830         [ -  + ]:       1010 :         if ( r )
    1831                 :            :                 {
    1832                 :            :                 // Add a FIN packet if there is one in the original trace.
    1833                 :            :                 int FIN_cnt = endp->IsOrig() ?
    1834                 :            :                                 endp->GetTCPAnalyzer()->Orig()->FIN_cnt :
    1835         [ #  # ]:          0 :                                 endp->GetTCPAnalyzer()->Resp()->FIN_cnt;
    1836                 :            : 
    1837         [ #  # ]:          0 :                 if ( FIN_cnt > 0 )
    1838                 :          0 :                         r->ScheduleFIN(endp->IsOrig());
    1839                 :            :                 }
    1840                 :       1010 :         }
    1841                 :            : 
    1842                 :        181 : void TCP_Analyzer::PacketWithRST()
    1843                 :            :         {
    1844                 :        181 :         const analyzer_list& children(GetChildren());
    1845         [ +  + ]:        493 :         LOOP_OVER_CONST_CHILDREN(i)
    1846                 :        312 :                 static_cast<TCP_ApplicationAnalyzer *>(*i)->PacketWithRST();
    1847                 :        181 :         }
    1848                 :            : 
    1849                 :      16528 : bool TCP_Analyzer::IsReuse(double t, const u_char* pkt)
    1850                 :            :         {
    1851                 :      16528 :         const struct tcphdr* tp = (const struct tcphdr*) pkt;
    1852                 :            : 
    1853         [ -  + ]:      16528 :         if ( unsigned(tp->th_off) < sizeof(struct tcphdr) / 4 )
    1854                 :            :                 // Bogus header, don't interpret further.
    1855                 :          0 :                 return false;
    1856                 :            : 
    1857                 :      16528 :         TCP_Endpoint* conn_orig = orig;
    1858                 :            : 
    1859                 :            :         // Reuse only occurs on initial SYN's, except for half connections
    1860                 :            :         // it can occur on SYN-acks.
    1861         [ +  + ]:      16528 :         if ( ! (tp->th_flags & TH_SYN) )
    1862                 :      16457 :                 return false;
    1863                 :            : 
    1864         [ +  + ]:         71 :         if ( (tp->th_flags & TH_ACK) )
    1865                 :            :                 {
    1866         [ +  - ]:         46 :                 if ( orig->state != TCP_ENDPOINT_INACTIVE )
    1867                 :            :                         // Not a half connection.
    1868                 :         46 :                         return false;
    1869                 :            : 
    1870                 :          0 :                 conn_orig = resp;
    1871                 :            :                 }
    1872                 :            : 
    1873         [ +  + ]:         25 :         if ( ! IsClosed() )
    1874                 :            :                 {
    1875                 :         22 :                 uint32 base_seq = ntohl(tp->th_seq);
    1876         [ +  + ]:         22 :                 if ( base_seq == conn_orig->StartSeq() )
    1877                 :         11 :                         return false;
    1878                 :            : 
    1879 [ +  - ][ -  + ]:         11 :                 if ( (tp->th_flags & TH_ACK) == 0 &&
         [ #  # ][ #  # ]
                 [ -  + ]
    1880                 :            :                      conn_orig->state == TCP_ENDPOINT_SYN_ACK_SENT &&
    1881                 :            :                      resp->state == TCP_ENDPOINT_INACTIVE &&
    1882                 :            :                      base_seq == resp->StartSeq() )
    1883                 :            :                         {
    1884                 :            :                         // This is an initial SYN with the right sequence
    1885                 :            :                         // number, and the state is consistent with the
    1886                 :            :                         // SYN & the SYN-ACK being flipped (e.g., due to
    1887                 :            :                         // reading from two interfaces w/ interrupt
    1888                 :            :                         // coalescence).  Don't treat this as a reuse.
    1889                 :            :                         // NextPacket() will flip set the connection
    1890                 :            :                         // state correctly
    1891                 :          0 :                         return false;
    1892                 :            :                         }
    1893                 :            : 
    1894         [ +  + ]:         11 :                 if ( conn_orig->state == TCP_ENDPOINT_SYN_SENT )
    1895                 :          7 :                         Weird("SYN_seq_jump");
    1896                 :            :                 else
    1897                 :         11 :                         Weird("active_connection_reuse");
    1898                 :            :                 }
    1899                 :            : 
    1900 [ +  + ][ -  + ]:          3 :         else if ( (orig->IsActive() || resp->IsActive()) &&
         [ +  - ][ -  + ]
                 [ -  + ]
    1901                 :            :                   orig->state != TCP_ENDPOINT_RESET &&
    1902                 :            :                   resp->state != TCP_ENDPOINT_RESET )
    1903                 :          0 :                 Weird("active_connection_reuse");
    1904                 :            : 
    1905 [ +  - ][ +  + ]:          3 :         else if ( t - Conn()->LastTime() < tcp_connection_linger &&
         [ -  + ][ -  + ]
    1906                 :            :                   orig->state != TCP_ENDPOINT_RESET &&
    1907                 :            :                   resp->state != TCP_ENDPOINT_RESET )
    1908                 :          0 :                 Weird("premature_connection_reuse");
    1909                 :            : 
    1910                 :      16528 :         return true;
    1911                 :            :         }
    1912                 :            : 
    1913                 :       1631 : void TCP_ApplicationAnalyzer::Init()
    1914                 :            :         {
    1915                 :       1631 :         Analyzer::Init();
    1916                 :            : 
    1917         [ +  - ]:       1631 :         if ( Parent()->GetTag() == AnalyzerTag::TCP )
    1918                 :       1631 :                 SetTCP(static_cast<TCP_Analyzer*>(Parent()));
    1919                 :       1631 :         }
    1920                 :            : 
    1921                 :            : void TCP_ApplicationAnalyzer::ProtocolViolation(const char* reason,
    1922                 :          0 :                                                 const char* data, int len)
    1923                 :            :         {
    1924                 :          0 :         TCP_Analyzer* tcp = TCP();
    1925                 :            : 
    1926   [ #  #  #  # ]:          0 :         if ( tcp &&
         [ #  # ][ #  # ]
                 [ #  # ]
    1927                 :            :              (tcp->IsPartial() || tcp->HadGap(false) || tcp->HadGap(true)) )
    1928                 :            :                 // Filter out incomplete connections.  Parsing them is
    1929                 :            :                 // too unreliable.
    1930                 :          0 :                 return;
    1931                 :            : 
    1932                 :          0 :         Analyzer::ProtocolViolation(reason, data, len);
    1933                 :            :         }
    1934                 :            : 
    1935                 :            : void TCP_ApplicationAnalyzer::DeliverPacket(int len, const u_char* data,
    1936                 :            :                                                 bool is_orig, int seq,
    1937                 :          0 :                                                 const IP_Hdr* ip, int caplen)
    1938                 :            :         {
    1939                 :          0 :         Analyzer::DeliverPacket(len, data, is_orig, seq, ip, caplen);
    1940 [ #  # ][ #  # ]:          0 :         DBG_LOG(DBG_DPD, "TCP_ApplicationAnalyzer ignoring DeliverPacket(%d, %s, %d, %p, %d) [%s%s]",
    1941                 :            :                         len, is_orig ? "T" : "F", seq, ip, caplen,
    1942                 :            :                         fmt_bytes((const char*) data, min(40, len)), len > 40 ? "..." : "");
    1943                 :          0 :         }
    1944                 :            : 
    1945                 :          0 : void TCP_ApplicationAnalyzer::SetEnv(bool /* is_orig */, char* name, char* val)
    1946                 :            :         {
    1947         [ #  # ]:          0 :         delete [] name;
    1948         [ #  # ]:          0 :         delete [] val;
    1949                 :          0 :         }
    1950                 :            : 
    1951                 :       1727 : void TCP_ApplicationAnalyzer::EndpointEOF(bool is_orig)
    1952                 :            :         {
    1953         [ +  + ]:       1727 :         SupportAnalyzer* sa = is_orig ? orig_supporters : resp_supporters;
    1954         [ +  + ]:       2444 :         for ( ; sa; sa = sa->Sibling() )
    1955                 :        717 :                 static_cast<TCP_SupportAnalyzer*>(sa)->EndpointEOF(is_orig);
    1956                 :       1727 :         }
    1957                 :            : 
    1958                 :       1727 : void TCP_ApplicationAnalyzer::TraceRewriterEOF(bool is_orig)
    1959                 :            :         {
    1960         [ +  + ]:       1727 :         SupportAnalyzer* sa = is_orig ? orig_supporters : resp_supporters;
    1961         [ +  + ]:       2444 :         for ( ; sa; sa = sa->Sibling() )
    1962                 :        717 :                 static_cast<TCP_SupportAnalyzer*>(sa)->TraceRewriterEOF(is_orig);
    1963                 :       1727 :         }
    1964                 :            : 
    1965                 :            : void TCP_ApplicationAnalyzer::ConnectionClosed(TCP_Endpoint* endpoint,
    1966                 :       1836 :                                         TCP_Endpoint* peer, int gen_event)
    1967                 :            :         {
    1968                 :            :         SupportAnalyzer* sa =
    1969         [ +  + ]:       1836 :                 endpoint->IsOrig() ? orig_supporters : resp_supporters;
    1970                 :            : 
    1971         [ +  + ]:       2579 :         for ( ; sa; sa = sa->Sibling() )
    1972                 :            :                 static_cast<TCP_SupportAnalyzer*>(sa)
    1973                 :        743 :                         ->ConnectionClosed(endpoint, peer, gen_event);
    1974                 :       1836 :         }
    1975                 :            : 
    1976                 :        667 : void TCP_ApplicationAnalyzer::ConnectionFinished(int half_finished)
    1977                 :            :         {
    1978         [ +  + ]:        939 :         for ( SupportAnalyzer* sa = orig_supporters; sa; sa = sa->Sibling() )
    1979                 :            :                 static_cast<TCP_SupportAnalyzer*>(sa)
    1980                 :        272 :                         ->ConnectionFinished(half_finished);
    1981                 :            : 
    1982         [ +  + ]:        939 :         for ( SupportAnalyzer* sa = resp_supporters; sa; sa = sa->Sibling() )
    1983                 :            :                 static_cast<TCP_SupportAnalyzer*>(sa)
    1984                 :        272 :                         ->ConnectionFinished(half_finished);
    1985                 :        667 :         }
    1986                 :            : 
    1987                 :         91 : void TCP_ApplicationAnalyzer::ConnectionReset()
    1988                 :            :         {
    1989         [ +  + ]:        132 :         for ( SupportAnalyzer* sa = orig_supporters; sa; sa = sa->Sibling() )
    1990                 :         41 :                 static_cast<TCP_SupportAnalyzer*>(sa)->ConnectionReset();
    1991                 :            : 
    1992         [ +  + ]:        132 :         for ( SupportAnalyzer* sa = resp_supporters; sa; sa = sa->Sibling() )
    1993                 :         41 :                 static_cast<TCP_SupportAnalyzer*>(sa)->ConnectionReset();
    1994                 :         91 :         }
    1995                 :            : 
    1996                 :        312 : void TCP_ApplicationAnalyzer::PacketWithRST()
    1997                 :            :         {
    1998         [ +  + ]:        443 :         for ( SupportAnalyzer* sa = orig_supporters; sa; sa = sa->Sibling() )
    1999                 :        131 :                 static_cast<TCP_SupportAnalyzer*>(sa)->PacketWithRST();
    2000                 :            : 
    2001         [ +  + ]:        443 :         for ( SupportAnalyzer* sa = resp_supporters; sa; sa = sa->Sibling() )
    2002                 :        131 :                 static_cast<TCP_SupportAnalyzer*>(sa)->PacketWithRST();
    2003                 :        312 :         }
    2004                 :            : 
    2005                 :          0 : TCPStats_Endpoint::TCPStats_Endpoint(TCP_Endpoint* e)
    2006                 :            :         {
    2007                 :          0 :         endp = e;
    2008                 :          0 :         num_pkts = 0;
    2009                 :          0 :         num_rxmit = 0;
    2010                 :          0 :         num_rxmit_bytes = 0;
    2011                 :          0 :         num_in_order = 0;
    2012                 :          0 :         num_OO = 0;
    2013                 :          0 :         num_repl = 0;
    2014                 :          0 :         max_top_seq = 0;
    2015                 :          0 :         last_id = 0;
    2016                 :          0 :         endian_type = ENDIAN_UNKNOWN;
    2017                 :          0 :         }
    2018                 :            : 
    2019                 :          0 : int endian_flip(int n)
    2020                 :            :         {
    2021                 :          0 :         return ((n & 0xff) << 8) | ((n & 0xff00) >> 8);
    2022                 :            :         }
    2023                 :            : 
    2024                 :            : int TCPStats_Endpoint::DataSent(double /* t */, int seq, int len, int caplen,
    2025                 :            :                         const u_char* /* data */,
    2026                 :          0 :                         const IP_Hdr* ip, const struct tcphdr* /* tp */)
    2027                 :            :         {
    2028         [ #  # ]:          0 :         if ( ++num_pkts == 1 )
    2029                 :            :                 { // First packet.
    2030                 :          0 :                 last_id = ntohs(ip->ID4());
    2031                 :          0 :                 return 0;
    2032                 :            :                 }
    2033                 :            : 
    2034                 :          0 :         int id = ntohs(ip->ID4());
    2035                 :            : 
    2036         [ #  # ]:          0 :         if ( id == last_id )
    2037                 :            :                 {
    2038                 :          0 :                 ++num_repl;
    2039                 :          0 :                 return 0;
    2040                 :            :                 }
    2041                 :            : 
    2042                 :          0 :         short id_delta = id - last_id;
    2043                 :          0 :         short id_endian_delta = endian_flip(id) - endian_flip(last_id);
    2044                 :            : 
    2045                 :          0 :         int abs_id_delta = id_delta > 0 ? id_delta : -id_delta;
    2046                 :            :         int abs_id_endian_delta =
    2047                 :          0 :                 id_endian_delta > 0 ? id_endian_delta : -id_endian_delta;
    2048                 :            : 
    2049                 :            :         int final_id_delta;
    2050                 :            : 
    2051         [ #  # ]:          0 :         if ( abs_id_delta < abs_id_endian_delta )
    2052                 :            :                 { // Consistent with big-endian.
    2053         [ #  # ]:          0 :                 if ( endian_type == ENDIAN_UNKNOWN )
    2054                 :          0 :                         endian_type = ENDIAN_BIG;
    2055         [ #  # ]:          0 :                 else if ( endian_type == ENDIAN_BIG )
    2056                 :            :                         ;
    2057                 :            :                 else
    2058                 :          0 :                         endian_type = ENDIAN_CONFUSED;
    2059                 :            : 
    2060                 :          0 :                 final_id_delta = id_delta;
    2061                 :            :                 }
    2062                 :            :         else
    2063                 :            :                 { // Consistent with little-endian.
    2064         [ #  # ]:          0 :                 if ( endian_type == ENDIAN_UNKNOWN )
    2065                 :          0 :                         endian_type = ENDIAN_LITTLE;
    2066         [ #  # ]:          0 :                 else if ( endian_type == ENDIAN_LITTLE )
    2067                 :            :                         ;
    2068                 :            :                 else
    2069                 :          0 :                         endian_type = ENDIAN_CONFUSED;
    2070                 :            : 
    2071                 :          0 :                 final_id_delta = id_endian_delta;
    2072                 :            :                 }
    2073                 :            : 
    2074 [ #  # ][ #  # ]:          0 :         if ( final_id_delta < 0 && final_id_delta > -256 )
    2075                 :            :                 {
    2076                 :          0 :                 ++num_OO;
    2077                 :          0 :                 return 0;
    2078                 :            :                 }
    2079                 :            : 
    2080                 :          0 :         last_id = id;
    2081                 :            : 
    2082                 :          0 :         ++num_in_order;
    2083                 :            : 
    2084                 :          0 :         int top_seq = seq + len;
    2085                 :            : 
    2086                 :          0 :         int data_in_flight = endp->LastSeq() - endp->AckSeq();
    2087         [ #  # ]:          0 :         if ( data_in_flight < 0 )
    2088                 :          0 :                 data_in_flight = 0;
    2089                 :            : 
    2090                 :          0 :         int seq_delta = top_seq - max_top_seq;
    2091         [ #  # ]:          0 :         if ( seq_delta <= 0 )
    2092                 :            :                 {
    2093 [ #  # ][ #  # ]:          0 :                 if ( ! ignore_keep_alive_rexmit || len > 1 || data_in_flight > 0 )
                 [ #  # ]
    2094                 :            :                         {
    2095                 :          0 :                         ++num_rxmit;
    2096                 :          0 :                         num_rxmit_bytes += len;
    2097                 :            :                         }
    2098                 :            : 
    2099                 :          0 :                 DEBUG_MSG("%.6f rexmit %d + %d <= %d data_in_flight = %d\n",
    2100                 :            :                         network_time, seq, len, max_top_seq, data_in_flight);
    2101                 :            : 
    2102         [ #  # ]:          0 :                 if ( tcp_rexmit )
    2103                 :            :                         {
    2104                 :          0 :                         val_list* vl = new val_list();
    2105                 :          0 :                         vl->append(endp->TCP()->BuildConnVal());
    2106                 :          0 :                         vl->append(new Val(endp->IsOrig(), TYPE_BOOL));
    2107                 :          0 :                         vl->append(new Val(seq, TYPE_COUNT));
    2108                 :          0 :                         vl->append(new Val(len, TYPE_COUNT));
    2109                 :          0 :                         vl->append(new Val(data_in_flight, TYPE_COUNT));
    2110                 :          0 :                         vl->append(new Val(endp->peer->window, TYPE_COUNT));
    2111                 :            : 
    2112                 :          0 :                         endp->TCP()->ConnectionEvent(tcp_rexmit, vl);
    2113                 :            :                         }
    2114                 :            :                 }
    2115                 :            :         else
    2116                 :          0 :                 max_top_seq = top_seq;
    2117                 :            : 
    2118                 :          0 :         return 0;
    2119                 :            :         }
    2120                 :            : 
    2121                 :          0 : RecordVal* TCPStats_Endpoint::BuildStats()
    2122                 :            :         {
    2123                 :          0 :         RecordVal* stats = new RecordVal(endpoint_stats);
    2124                 :            : 
    2125                 :          0 :         stats->Assign(0, new Val(num_pkts,TYPE_COUNT));
    2126                 :          0 :         stats->Assign(1, new Val(num_rxmit,TYPE_COUNT));
    2127                 :          0 :         stats->Assign(2, new Val(num_rxmit_bytes,TYPE_COUNT));
    2128                 :          0 :         stats->Assign(3, new Val(num_in_order,TYPE_COUNT));
    2129                 :          0 :         stats->Assign(4, new Val(num_OO,TYPE_COUNT));
    2130                 :          0 :         stats->Assign(5, new Val(num_repl,TYPE_COUNT));
    2131                 :          0 :         stats->Assign(6, new Val(endian_type,TYPE_COUNT));
    2132                 :            : 
    2133                 :          0 :         return stats;
    2134                 :            :         }
    2135                 :            : 
    2136                 :          0 : TCPStats_Analyzer::TCPStats_Analyzer(Connection* c)
    2137                 :          0 : : TCP_ApplicationAnalyzer(AnalyzerTag::TCPStats, c)
    2138                 :            :         {
    2139                 :          0 :         }
    2140                 :            : 
    2141                 :          0 : TCPStats_Analyzer::~TCPStats_Analyzer()
    2142                 :            :         {
    2143                 :          0 :         delete orig_stats;
    2144                 :          0 :         delete resp_stats;
    2145 [ #  # ][ #  # ]:          0 :         }
                 [ #  # ]
    2146                 :            : 
    2147                 :          0 : void TCPStats_Analyzer::Init()
    2148                 :            :         {
    2149                 :          0 :         TCP_ApplicationAnalyzer::Init();
    2150                 :            : 
    2151                 :          0 :         orig_stats = new TCPStats_Endpoint(TCP()->Orig());
    2152                 :          0 :         resp_stats = new TCPStats_Endpoint(TCP()->Resp());
    2153                 :          0 :         }
    2154                 :            : 
    2155                 :          0 : void TCPStats_Analyzer::Done()
    2156                 :            :         {
    2157                 :          0 :         TCP_ApplicationAnalyzer::Done();
    2158                 :            : 
    2159                 :          0 :         val_list* vl = new val_list;
    2160                 :          0 :         vl->append(BuildConnVal());
    2161                 :          0 :         vl->append(orig_stats->BuildStats());
    2162                 :          0 :         vl->append(resp_stats->BuildStats());
    2163                 :          0 :         ConnectionEvent(conn_stats, vl);
    2164                 :          0 :         }
    2165                 :            : 
    2166                 :          0 : void TCPStats_Analyzer::DeliverPacket(int len, const u_char* data, bool is_orig, int seq, const IP_Hdr* ip, int caplen)
    2167                 :            :         {
    2168                 :          0 :         TCP_ApplicationAnalyzer::DeliverPacket(len, data, is_orig, seq, ip, caplen);
    2169                 :            : 
    2170         [ #  # ]:          0 :         if ( is_orig )
    2171                 :          0 :                 orig_stats->DataSent(network_time, seq, len, caplen, data, ip, 0);
    2172                 :            :         else
    2173                 :          0 :                 resp_stats->DataSent(network_time, seq, len, caplen, data, ip, 0);
    2174 [ +  - ][ +  - ]:          6 :         }

Generated by: LCOV version 1.8