LCOV - code coverage report
Current view: top level - src - TCP_Endpoint.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 107 133 80.5 %
Date: 2010-12-13 Functions: 18 23 78.3 %
Branches: 52 92 56.5 %

           Branch data     Line data    Source code
       1                 :            : // $Id: TCP_Endpoint.cc 6219 2008-10-01 05:39:07Z vern $
       2                 :            : //
       3                 :            : // See the file "COPYING" in the main distribution directory for copyright.
       4                 :            : 
       5                 :            : #include "Net.h"
       6                 :            : #include "NetVar.h"
       7                 :            : #include "TCP.h"
       8                 :            : #include "TCP_Rewriter.h"
       9                 :            : #include "TCP_Reassembler.h"
      10                 :            : #include "Sessions.h"
      11                 :            : #include "Event.h"
      12                 :            : #include "File.h"
      13                 :            : #include "Val.h"
      14                 :            : 
      15                 :       1876 : TCP_Endpoint::TCP_Endpoint(TCP_Analyzer* arg_analyzer, int arg_is_orig)
      16                 :            :         {
      17                 :       1876 :         contents_processor = 0;
      18                 :       1876 :         prev_state = state = TCP_ENDPOINT_INACTIVE;
      19                 :       1876 :         peer = 0;
      20                 :       1876 :         start_time = last_time = 0.0;
      21                 :       1876 :         start_seq = last_seq = ack_seq = 0;
      22                 :       1876 :         last_seq_high = ack_seq_high = 0;
      23                 :       1876 :         window = 0;
      24                 :       1876 :         window_scale = 0;
      25                 :       1876 :         window_seq = window_ack_seq = 0;
      26                 :       1876 :         contents_start_seq = 0;
      27                 :       1876 :         SYN_cnt = FIN_cnt = RST_cnt = 0;
      28                 :       1876 :         did_close = 0;
      29                 :       1876 :         contents_file = 0;
      30                 :       1876 :         tcp_analyzer = arg_analyzer;
      31                 :       1876 :         is_orig = arg_is_orig;
      32                 :            : 
      33                 :            :         src_addr = is_orig ? tcp_analyzer->Conn()->RespAddr() :
      34 [ +  + ][ #  # ]:       1876 :                                 tcp_analyzer->Conn()->OrigAddr();
      35                 :            :         dst_addr = is_orig ? tcp_analyzer->Conn()->OrigAddr() :
      36 [ +  + ][ #  # ]:       1876 :                                 tcp_analyzer->Conn()->RespAddr();
      37                 :            : 
      38                 :            : #ifdef BROv6
      39                 :            :         checksum_base = ones_complement_checksum((void*) src_addr, 16, 0);
      40                 :            :         checksum_base = ones_complement_checksum((void*) dst_addr, 16, checksum_base);
      41                 :            : #else
      42                 :       1876 :         checksum_base = ones_complement_checksum((void*) src_addr, 4, 0);
      43                 :       1876 :         checksum_base = ones_complement_checksum((void*) dst_addr, 4, checksum_base);
      44                 :            : #endif
      45                 :            :         // Note, for IPv6, strictly speaking this field is 32 bits
      46                 :            :         // rather than 16 bits.  But because the upper bits are all zero,
      47                 :            :         // we get the same checksum either way.  The same applies to
      48                 :            :         // later when we add in the data length in ValidChecksum().
      49                 :       1876 :         checksum_base += htons(IPPROTO_TCP);
      50                 :       1876 :         }
      51                 :            : 
      52                 :       1876 : TCP_Endpoint::~TCP_Endpoint()
      53                 :            :         {
      54 [ +  - ][ #  # ]:       1876 :         delete contents_processor;
      55                 :       1876 :         Unref(contents_file);
      56                 :       1876 :         }
      57                 :            : 
      58                 :       1876 : void TCP_Endpoint::Done()
      59                 :            :         {
      60         [ +  - ]:       1876 :         if ( contents_processor )
      61                 :       1876 :                 contents_processor->Done();
      62                 :       1876 :         }
      63                 :            : 
      64                 :       1876 : void TCP_Endpoint::SetPeer(TCP_Endpoint* p)
      65                 :            :         {
      66                 :       1876 :         peer = p;
      67         [ +  + ]:       1876 :         if ( IsOrig() )
      68                 :            :                 // Only one Endpoint adds the initial state to the counter.
      69                 :        938 :                 sessions->tcp_stats.StateEntered(state, peer->state);
      70                 :       1876 :         }
      71                 :            : 
      72                 :          0 : int TCP_Endpoint::HadGap() const
      73                 :            :         {
      74 [ #  # ][ #  # ]:          0 :         return contents_processor && contents_processor->HadGap();
      75                 :            :         }
      76                 :            : 
      77                 :       1876 : void TCP_Endpoint::AddReassembler(TCP_Reassembler* arg_contents_processor)
      78                 :            :         {
      79         [ +  - ]:       1876 :         if ( contents_processor != arg_contents_processor )
      80         [ -  + ]:       1876 :                 delete contents_processor;
      81                 :       1876 :         contents_processor = arg_contents_processor;
      82                 :            : 
      83         [ -  + ]:       1876 :         if ( contents_file )
      84                 :          0 :                 contents_processor->SetContentsFile(contents_file);
      85                 :       1876 :         }
      86                 :            : 
      87                 :       1139 : int TCP_Endpoint::DataPending() const
      88                 :            :         {
      89         [ +  - ]:       1139 :         if ( contents_processor )
      90                 :       1139 :                 return contents_processor->DataPending();
      91                 :            :         else
      92                 :       1139 :                 return 0;
      93                 :            :         }
      94                 :            : 
      95                 :       1978 : int TCP_Endpoint::HasUndeliveredData() const
      96                 :            :         {
      97         [ +  - ]:       1978 :         if ( contents_processor )
      98                 :       1978 :                 return contents_processor->HasUndeliveredData();
      99                 :            :         else
     100                 :       1978 :                 return 0;
     101                 :            :         }
     102                 :            : 
     103                 :      17976 : void TCP_Endpoint::CheckEOF()
     104                 :            :         {
     105         [ +  - ]:      17976 :         if ( contents_processor )
     106                 :      17976 :                 contents_processor->CheckEOF();
     107                 :      17976 :         }
     108                 :            : 
     109                 :          0 : void TCP_Endpoint::SizeBufferedData(int& waiting_on_hole, int& waiting_on_ack)
     110                 :            :         {
     111         [ #  # ]:          0 :         if ( contents_processor )
     112                 :          0 :                 contents_processor->SizeBufferedData(waiting_on_hole, waiting_on_ack);
     113                 :            :         else
     114                 :          0 :                 waiting_on_hole = waiting_on_ack = 0;
     115                 :          0 :         }
     116                 :            : 
     117                 :      17976 : int TCP_Endpoint::ValidChecksum(const struct tcphdr* tp, int len) const
     118                 :            :         {
     119                 :      17976 :         uint32 sum = checksum_base;
     120                 :      17976 :         int tcp_len = tp->th_off * 4 + len;
     121                 :            : 
     122         [ +  + ]:      17976 :         if ( len % 2 == 1 )
     123                 :            :                 // Add in pad byte.
     124                 :       1995 :                 sum += htons(((const u_char*) tp)[tcp_len - 1] << 8);
     125                 :            : 
     126                 :      17976 :         sum += htons((unsigned short) tcp_len); // fill out pseudo header
     127                 :      17976 :         sum = ones_complement_checksum((void*) tp, tcp_len, sum);
     128                 :            : 
     129                 :      17976 :         return sum == 0xffff;
     130                 :            :         }
     131                 :            : 
     132                 :       7276 : static inline bool is_handshake(EndpointState state)
     133                 :            :         {
     134                 :            :         return state == TCP_ENDPOINT_INACTIVE ||
     135                 :            :                 state == TCP_ENDPOINT_SYN_SENT ||
     136 [ +  + ][ +  + ]:       7276 :                 state == TCP_ENDPOINT_SYN_ACK_SENT;
                 [ +  + ]
     137                 :            :         }
     138                 :            : 
     139                 :       3029 : void TCP_Endpoint::SetState(EndpointState new_state)
     140                 :            :         {
     141         [ +  - ]:       3029 :         if ( new_state != state )
     142                 :            :                 {
     143                 :            :                 // Activate inactivity timer if this transition finishes the
     144                 :            :                 // handshake.
     145         [ +  + ]:       3029 :                 if ( ! is_handshake(new_state) )
     146 [ +  + ][ +  + ]:       2550 :                         if ( is_handshake(state) && is_handshake(peer->state) )
                 [ +  + ]
     147                 :        927 :                                 tcp_analyzer->Conn()->SetInactivityTimeout(tcp_inactivity_timeout);
     148                 :            : 
     149                 :       3029 :                 prev_state = state;
     150                 :       3029 :                 state = new_state;
     151         [ +  + ]:       3029 :                 if ( IsOrig() )
     152                 :            :                         sessions->tcp_stats.ChangeState(prev_state, state,
     153                 :       1657 :                                                 peer->state, peer->state);
     154                 :            :                 else
     155                 :            :                         sessions->tcp_stats.ChangeState(peer->state, peer->state,
     156                 :       1372 :                                                 prev_state, state);
     157                 :            :                 }
     158                 :       3029 :         }
     159                 :            : 
     160                 :      33088 : bro_int_t TCP_Endpoint::Size() const
     161                 :            :         {
     162                 :            :         bro_int_t size;
     163                 :            : 
     164                 :      33088 :         uint64 last_seq_64 = (uint64(last_seq_high) << 32) | last_seq;
     165                 :      33088 :         uint64 ack_seq_64 = (uint64(ack_seq_high) << 32) | ack_seq;
     166         [ +  + ]:      33088 :         if ( last_seq_64 > ack_seq_64 )
     167                 :      16110 :                 size = last_seq_64 - start_seq;
     168                 :            :         else
     169                 :      16978 :                 size = ack_seq_64 - start_seq;
     170                 :            : 
     171                 :            :         // Don't include SYN octet in sequence space.  For partial connections
     172                 :            :         // (no SYN seen), we're still careful to adjust start_seq as though
     173                 :            :         // there was an initial SYN octet, because if we don't then the
     174                 :            :         // packet reassembly code gets confused.
     175         [ +  + ]:      33088 :         if ( size != 0 )
     176                 :      31642 :                 --size;
     177                 :            : 
     178 [ +  + ][ +  + ]:      33088 :         if ( FIN_cnt > 0 && size != 0 )
     179                 :       2328 :                 --size; // don't include FIN octet.
     180                 :            : 
     181                 :      33088 :         return size;
     182                 :            :         }
     183                 :            : 
     184                 :            : int TCP_Endpoint::DataSent(double t, int seq, int len, int caplen,
     185                 :            :                                 const u_char* data,
     186                 :       9174 :                                 const IP_Hdr* ip, const struct tcphdr* tp)
     187                 :            :         {
     188                 :       9174 :         int status = 0;
     189                 :            : 
     190 [ +  - ][ +  - ]:       9174 :         if ( contents_processor && caplen >= len )
     191                 :       9174 :                 status = contents_processor->DataSent(t, seq, len, data);
     192                 :            : 
     193         [ -  + ]:       9174 :         if ( caplen <= 0 )
     194                 :          0 :                 return status;
     195                 :            : 
     196 [ -  + ][ #  # ]:       9174 :         if ( contents_file && ! contents_processor && 
                 [ #  # ]
     197                 :            :              seq + len > contents_start_seq )
     198                 :            :                 {
     199                 :          0 :                 int under_seq = contents_start_seq - seq;
     200         [ #  # ]:          0 :                 if ( under_seq > 0 )
     201                 :            :                         {
     202                 :          0 :                         seq += under_seq;
     203                 :          0 :                         data += under_seq;
     204                 :          0 :                         len -= under_seq;
     205                 :            :                         }
     206                 :            : 
     207                 :            :                 // DEBUG_MSG("%d: seek %d, data=%02x len=%d\n", IsOrig(), seq - contents_start_seq, *data, len);
     208                 :          0 :                 FILE* f = contents_file->Seek(seq - contents_start_seq);
     209                 :            : 
     210         [ #  # ]:          0 :                 if ( fwrite(data, 1, len, f) < unsigned(len) )
     211                 :            :                         // ### this should really generate an event
     212                 :          0 :                         internal_error("contents write failed");
     213                 :            :                 }
     214                 :            : 
     215                 :       9174 :         return status;
     216                 :            :         }
     217                 :            : 
     218                 :      17321 : void TCP_Endpoint::AckReceived(int seq)
     219                 :            :         {
     220         [ +  - ]:      17321 :         if ( contents_processor )
     221                 :      17321 :                 contents_processor->AckReceived(seq);
     222                 :      17321 :         }
     223                 :            : 
     224                 :          0 : void TCP_Endpoint::SetContentsFile(BroFile* f)
     225                 :            :         {
     226                 :          0 :         Ref(f);
     227                 :          0 :         contents_file = f;
     228                 :          0 :         contents_start_seq = last_seq - start_seq;
     229                 :            : 
     230         [ #  # ]:          0 :         if ( contents_start_seq == 0 )
     231                 :          0 :                 contents_start_seq = 1; // skip SYN
     232                 :            : 
     233         [ #  # ]:          0 :         if ( contents_processor )
     234                 :          0 :                 contents_processor->SetContentsFile(contents_file);
     235                 :          0 :         }
     236                 :            : 
     237                 :      17976 : int TCP_Endpoint::CheckHistory(uint32 mask, char code)
     238                 :            :         {
     239         [ +  + ]:      17976 :         if ( ! IsOrig() )
     240                 :            :                 {
     241                 :       9919 :                 mask <<= 16;
     242                 :       9919 :                 code = tolower(code);
     243                 :            :                 }
     244                 :            : 
     245                 :      17976 :         return tcp_analyzer->Conn()->CheckHistory(mask, code);
     246                 :            :         }
     247                 :            : 
     248                 :         99 : void TCP_Endpoint::AddHistory(char code)
     249                 :            :         {
     250         [ +  + ]:         99 :         if ( ! IsOrig() )
     251                 :         56 :                 code = tolower(code);
     252                 :            : 
     253                 :         99 :         tcp_analyzer->Conn()->AddHistory(code);
     254 [ +  - ][ +  - ]:        105 :         }
     255                 :          3 : 

Generated by: LCOV version 1.8