LCOV - code coverage report
Current view: top level - src - TCP_Rewriter.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 7 719 1.0 %
Date: 2010-12-13 Functions: 3 94 3.2 %
Branches: 3 542 0.6 %

           Branch data     Line data    Source code
       1                 :            : // $Id: TCP_Rewriter.cc 6008 2008-07-23 00:24:22Z vern $
       2                 :            : 
       3                 :            : //  Overview of TCP trace rewriter:
       4                 :            : //
       5                 :            : //  1. Timestamp: Consider every packet arrival at a certain endpoint
       6                 :            : //  in the original trace as a tick for the endpoint; a packet will be
       7                 :            : //  dumped into the new trace (possibly with different content) in the
       8                 :            : //  tick (enforced by flush_rewriter_packet). When the user writes data
       9                 :            : //  into the new trace, the packet will carry a timestamp of the
      10                 :            : //  current tick, or the next tick if data is generated between
      11                 :            : //  ticks. Users may also choose to Push data, in which case the packet
      12                 :            : //  carries a timestamp of current network time. This gives us the
      13                 :            : //  'freshness' of timestamps.
      14                 :            : //
      15                 :            : //  2. Ordering of contents: user may choose to push contents in order
      16                 :            : //  to enforce ordering of contents between two directions, however,
      17                 :            : //  contents MIGHT be already dumped BEFORE they are pushed, once they
      18                 :            : //  are written into the trace. (similar to PUSH in TCP)
      19                 :            : //
      20                 :            : //  3. Acknowledgements: when a packet is dumped at a time when there
      21                 :            : //  is no corresponding packet in the original trace, an articial
      22                 :            : //  acknowledgement is generated from the peer with the same
      23                 :            : //  timestamp. This guarantees that additional packets will have
      24                 :            : //  acknowledgements. For those packets dumped at 'ticks', there
      25                 :            : //  should be corresponding acknowledgement packets in the original
      26                 :            : //  trace already, so we do not generate further artificial
      27                 :            : //  acknowledgement packets.
      28                 :            : //
      29                 :            : //  4. SYN, RST, FIN: SYN/RST packets in the new trace do not carry
      30                 :            : //  payloads -- additional packets may be generated for payloads. FIN
      31                 :            : //  packets are generated only when user calls ScheduleFIN, which by
      32                 :            : //  default corresponds to the moment that contents of the flow is
      33                 :            : //  completely delivered, which is usually when the FIN appears in the
      34                 :            : //  original trace. Change: now we will try to allow SYN/RST packets
      35                 :            : //  to carry payloads if they originally do.
      36                 :            : 
      37                 :            : #include "config.h"
      38                 :            : 
      39                 :            : #include <assert.h>
      40                 :            : #include <stdlib.h>
      41                 :            : 
      42                 :            : #include "Event.h"
      43                 :            : #include "Net.h"
      44                 :            : #include "TCP_Rewriter.h"
      45                 :            : 
      46                 :            : #define MSG_PREFIX      "TCP trace rewriter: "
      47                 :            : #define DEBUG_MSG_A(x...)
      48                 :            : // #define DEBUG_MSG_A  DEBUG_MSG
      49                 :            : 
      50                 :            : static IP_IDSet* ip_id_set = 0; // <IP, IP-ID> pairs in the output trace
      51                 :            : int num_packets_held, num_packets_cleaned;
      52                 :            : 
      53                 :            : TCP_TracePacket::TCP_TracePacket(TCP_Rewriter* arg_trace_rewriter,
      54                 :            :                                  int arg_packet_seq, double t, int arg_is_orig,
      55                 :            :                                  const struct pcap_pkthdr* arg_hdr,
      56                 :          0 :                                  int MTU, int initial_size)
      57                 :            :         {
      58                 :          0 :         trace_rewriter = arg_trace_rewriter;
      59                 :          0 :         pcap_hdr = *arg_hdr;
      60                 :          0 :         packet_seq = arg_packet_seq;
      61                 :          0 :         timestamp = t;
      62                 :          0 :         is_orig = arg_is_orig;
      63                 :          0 :         mtu = MTU;
      64                 :          0 :         pkt = new u_char[initial_size];
      65                 :          0 :         buffer_size = initial_size;
      66                 :            : 
      67                 :          0 :         buffer_offset = 0;
      68                 :          0 :         ip_offset = tcp_offset = data_offset = -1;
      69                 :          0 :         reuse = 0;
      70                 :          0 :         FIN_scheduled = 0;
      71                 :          0 :         on_hold = 0;
      72                 :          0 :         seq_gap = 0;
      73                 :          0 :         packet_val = 0;
      74                 :          0 :         packet_val = PacketVal();
      75                 :          0 :         has_reserved_slot = 0;
      76                 :          0 :         predicted_as_empty_place_holder = 0;
      77                 :          0 :         }
      78                 :            : 
      79                 :          0 : TCP_TracePacket::~TCP_TracePacket()
      80                 :            :         {
      81                 :          0 :         packet_val->SetOrigin(0);
      82                 :          0 :         Unref(packet_val);
      83 [ #  #  #  #  # :          0 :         if ( pkt )
                      # ]
      84 [ #  # ][ #  # ]:          0 :                 delete [] pkt;
                 [ #  # ]
      85 [ #  # ][ #  # ]:          0 :         }
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
                 [ #  # ]
      86                 :            : 
      87                 :          0 : int TCP_TracePacket::AppendLinkHeader(const u_char* chunk, int len)
      88                 :            :         {
      89 [ #  # ][ #  # ]:          0 :         if ( ip_offset >= 0 && ip_offset != buffer_offset )
      90                 :          0 :                 internal_error(MSG_PREFIX "link header must be appended before IP header");
      91                 :            : 
      92         [ #  # ]:          0 :         if ( ! Append(chunk, len) )
      93                 :          0 :                 return 0;
      94                 :            : 
      95                 :          0 :         ip_offset = buffer_offset;
      96                 :          0 :         return 1;
      97                 :            :         }
      98                 :            : 
      99                 :          0 : int TCP_TracePacket::AppendIPHeader(const u_char* chunk, int len)
     100                 :            :         {
     101 [ #  # ][ #  # ]:          0 :         if ( tcp_offset >= 0 && tcp_offset != buffer_offset )
     102                 :          0 :                 internal_error(MSG_PREFIX "IP header must be appended before tcp header");
     103                 :            : 
     104         [ #  # ]:          0 :         if ( ! Append(chunk, len) )
     105                 :          0 :                 return 0;
     106                 :            : 
     107                 :          0 :         tcp_offset = buffer_offset;
     108                 :          0 :         return 1;
     109                 :            :         }
     110                 :            : 
     111                 :          0 : int TCP_TracePacket::AppendTCPHeader(const u_char* chunk, int len)
     112                 :            :         {
     113 [ #  # ][ #  # ]:          0 :         if ( data_offset >= 0 && data_offset != buffer_offset )
     114                 :          0 :                 internal_error(MSG_PREFIX "tcp header must be appended before payload");
     115                 :            : 
     116         [ #  # ]:          0 :         if ( tcp_offset == buffer_offset )
     117                 :            :                 { // first TCP header chunk
     118                 :          0 :                 int extra = (tcp_offset - ip_offset) % 4;
     119         [ #  # ]:          0 :                 if ( extra )
     120                 :            :                         {
     121                 :          0 :                         DEBUG_MSG(MSG_PREFIX "padding IP header");
     122         [ #  # ]:          0 :                         if ( ! AppendIPHeader(0, 4 - extra) )
     123                 :          0 :                                 return 0;
     124                 :            :                         }
     125                 :            :                 }
     126                 :            : 
     127         [ #  # ]:          0 :         if ( ! Append(chunk, len) )
     128                 :          0 :                 return 0;
     129                 :            : 
     130                 :          0 :         data_offset = buffer_offset;
     131                 :          0 :         return 1;
     132                 :            :         }
     133                 :            : 
     134                 :          0 : int TCP_TracePacket::AppendData(const u_char* chunk, int len)
     135                 :            :         {
     136                 :            :         // All headers must be appended before any data.
     137 [ #  # ][ #  # ]:          0 :         ASSERT(ip_offset >= 0 && tcp_offset >= 0 && data_offset >= 0);
         [ #  # ][ #  # ]
     138                 :            : 
     139         [ #  # ]:          0 :         if ( data_offset == buffer_offset )
     140                 :            :                 { // first data chunk
     141                 :          0 :                 int extra = (data_offset - tcp_offset) % 4;
     142         [ #  # ]:          0 :                 if ( extra )
     143                 :            :                         {
     144                 :          0 :                         DEBUG_MSG(MSG_PREFIX "%.6f padding tcp header -- original header range: %d - %d\n",
     145                 :            :                                         network_time, tcp_offset, data_offset);
     146         [ #  # ]:          0 :                         if ( ! AppendTCPHeader(0, 4 - extra) )
     147                 :          0 :                                 return 0;
     148                 :            :                         }
     149                 :            :                 }
     150                 :            : 
     151         [ #  # ]:          0 :         if ( ! Append(chunk, len) )
     152                 :          0 :                 return 0;
     153                 :            : 
     154                 :          0 :         return 1;
     155                 :            :         }
     156                 :            : 
     157                 :          0 : int TCP_TracePacket::Append(const u_char* chunk, int len)
     158                 :            :         {
     159         [ #  # ]:          0 :         if ( buffer_offset + len > buffer_size )
     160                 :            :                 {
     161         [ #  # ]:          0 :                 if ( buffer_offset + len > mtu )
     162                 :          0 :                         return 0;
     163                 :            : 
     164                 :          0 :                 u_char* tmp = new u_char[mtu];
     165         [ #  # ]:          0 :                 for ( int i = 0 ; i < buffer_size; ++i )
     166                 :          0 :                         tmp[i] = pkt[i];
     167                 :            : 
     168         [ #  # ]:          0 :                 delete [] pkt;
     169                 :          0 :                 pkt = tmp;
     170                 :          0 :                 buffer_size = mtu;
     171                 :            :                 }
     172                 :            : 
     173         [ #  # ]:          0 :         ASSERT(buffer_offset + len <= buffer_size);
     174                 :            : 
     175         [ #  # ]:          0 :         if ( chunk )
     176                 :            :                 {
     177         [ #  # ]:          0 :                 if ( pkt + buffer_offset != chunk )
     178                 :          0 :                         memcpy(pkt + buffer_offset, chunk, len);
     179                 :            :                 }
     180                 :            :         else
     181                 :            :                 // Fill with 0.
     182                 :          0 :                 memset(pkt + buffer_offset, 0, len);
     183                 :            : 
     184                 :          0 :         buffer_offset += len;
     185                 :          0 :         return 1;
     186                 :            :         }
     187                 :            : 
     188                 :          0 : uint32 TCP_TracePacket::GetSeq() const
     189                 :            :         {
     190 [ #  # ][ #  # ]:          0 :         ASSERT(tcp_offset >= ip_offset + int(sizeof(struct ip)) &&
                 [ #  # ]
     191                 :            :                buffer_offset >= tcp_offset + int(sizeof(struct tcphdr)));
     192                 :            : 
     193                 :          0 :         struct tcphdr* tp = (struct tcphdr*) (pkt + tcp_offset);
     194                 :          0 :         return ntohl(tp->th_seq);
     195                 :            :         }
     196                 :            : 
     197                 :          0 : void TCP_TracePacket::SetSeq(uint32 seq)
     198                 :            :         {
     199 [ #  # ][ #  # ]:          0 :         ASSERT(tcp_offset >= ip_offset + int(sizeof(struct ip)) &&
                 [ #  # ]
     200                 :            :                buffer_offset >= tcp_offset + int(sizeof(struct tcphdr)));
     201                 :            : 
     202                 :          0 :         struct tcphdr* tp = (struct tcphdr*) (pkt + tcp_offset);
     203                 :          0 :         tp->th_seq = htonl(seq);
     204                 :          0 :         }
     205                 :            : 
     206                 :          0 : uint32 TCP_TracePacket::GetAck() const
     207                 :            :         {
     208 [ #  # ][ #  # ]:          0 :         ASSERT(tcp_offset >= ip_offset + int(sizeof(struct ip)) &&
                 [ #  # ]
     209                 :            :                buffer_offset >= tcp_offset + int(sizeof(struct tcphdr)));
     210                 :            : 
     211                 :          0 :         struct tcphdr* tp = (struct tcphdr*) (pkt + tcp_offset);
     212                 :          0 :         return ntohl(tp->th_ack);
     213                 :            :         }
     214                 :            : 
     215                 :          0 : void TCP_TracePacket::SetAck(uint32 ack)
     216                 :            :         {
     217 [ #  # ][ #  # ]:          0 :         ASSERT(tcp_offset >= ip_offset + int(sizeof(struct ip)) &&
                 [ #  # ]
     218                 :            :                buffer_offset >= tcp_offset + int(sizeof(struct tcphdr)));
     219                 :            : 
     220                 :          0 :         struct tcphdr* tp = (struct tcphdr*) (pkt + tcp_offset);
     221                 :          0 :         tp->th_ack = htonl(ack);
     222                 :          0 :         }
     223                 :            : 
     224                 :          0 : int TCP_TracePacket::GetTCP_Flag(int which) const
     225                 :            :         {
     226 [ #  # ][ #  # ]:          0 :         ASSERT(tcp_offset >= ip_offset + int(sizeof(struct ip)) &&
                 [ #  # ]
     227                 :            :                buffer_offset >= tcp_offset + int(sizeof(struct tcphdr)));
     228                 :            : 
     229                 :          0 :         struct tcphdr* tp = (struct tcphdr*) (pkt + tcp_offset);
     230                 :          0 :         return tp->th_flags & which;
     231                 :            :         }
     232                 :            : 
     233                 :          0 : void TCP_TracePacket::SetTCP_Flag(int which, int value)
     234                 :            :         {
     235 [ #  # ][ #  # ]:          0 :         ASSERT(tcp_offset >= ip_offset + int(sizeof(struct ip)) &&
                 [ #  # ]
     236                 :            :                buffer_offset >= tcp_offset + int(sizeof(struct tcphdr)));
     237                 :            : 
     238                 :          0 :         struct tcphdr* tp = (struct tcphdr*) (pkt + tcp_offset);
     239                 :            : 
     240         [ #  # ]:          0 :         if ( value )
     241                 :          0 :                 tp->th_flags |= which;
     242                 :            :         else
     243                 :          0 :                 tp->th_flags &= (~which);
     244                 :          0 :         }
     245                 :            : 
     246                 :          0 : int TCP_TracePacket::PayloadLength() const
     247                 :            :         {
     248         [ #  # ]:          0 :         if ( data_offset < 0 )
     249                 :          0 :                 return 0;
     250                 :            : 
     251                 :          0 :         return buffer_offset - data_offset;
     252                 :            :         }
     253                 :            : 
     254                 :          0 : int TCP_TracePacket::SeqLength() const
     255                 :            :         {
     256                 :          0 :         int len = PayloadLength();
     257                 :          0 :         struct tcphdr* tp = (struct tcphdr*) (pkt + tcp_offset);
     258                 :            : 
     259         [ #  # ]:          0 :         if ( tp->th_flags & TH_SYN )
     260                 :          0 :                 ++len;
     261                 :            : 
     262         [ #  # ]:          0 :         if ( tp->th_flags & TH_FIN )
     263                 :          0 :                 ++len;
     264                 :            : 
     265                 :          0 :         return len;
     266                 :            :         }
     267                 :            : 
     268                 :            : int TCP_TracePacket::Finish(struct pcap_pkthdr*& hdr,
     269                 :            :                             const u_char*& arg_pkt, int& length,
     270                 :          0 :                             ipaddr32_t anon_src, ipaddr32_t anon_dst)
     271                 :            :         {
     272                 :            :         // Set length fields in headers and compute checksums.
     273 [ #  # ][ #  # ]:          0 :         if ( tcp_offset < ip_offset + int(sizeof(struct ip)) ||
     274                 :            :              data_offset < tcp_offset + int(sizeof(struct tcphdr)) )
     275                 :          0 :                 return 0;
     276                 :            : 
     277                 :          0 :         struct ip* ip = (struct ip*) (pkt + ip_offset);
     278                 :          0 :         struct tcphdr* tp = (struct tcphdr*) (pkt + tcp_offset);
     279                 :            : 
     280                 :            :         // TCP header.
     281         [ #  # ]:          0 :         ASSERT((data_offset - tcp_offset) % 4 == 0);
     282                 :            : 
     283                 :          0 :         tp->th_off = (data_offset - tcp_offset) >> 2;
     284                 :          0 :         tp->th_x2 = 0;
     285                 :            : 
     286                 :            :         // Shall we instead let URG flag&point stay?
     287                 :            :         // tp->th_flags &= (~TH_URG);    // set URG to 0
     288                 :            :         // tp->th_urp = 0;           // clear urgent pointer
     289                 :            : 
     290                 :            :         // Fix IP addresses before computing the TCP checksum
     291         [ #  # ]:          0 :         if ( anonymize_ip_addr )
     292                 :            :                 {
     293                 :          0 :                 ip->ip_src.s_addr = anon_src;
     294                 :          0 :                 ip->ip_dst.s_addr = anon_dst;
     295                 :            :                 }
     296                 :            : 
     297                 :          0 :         tp->th_sum = 0;
     298                 :          0 :         tp->th_sum = 0xffff - tcp_checksum(ip, tp, PayloadLength());
     299                 :            : 
     300                 :            :         // IP header.
     301                 :            : 
     302                 :            :         // What to do with ip_id? One way is to choose a pseudo-random
     303                 :            :         // number as the new id. We try to keep the original ID unless
     304                 :            :         // it would cause a conflict, in which case we increment the
     305                 :            :         // ID till there is no conflict.
     306                 :            :         //
     307                 :            :         // This is too expensive -- and ID conflicts do not really
     308                 :            :         // matter because there will never be fragmentation.
     309                 :            :         // Fix: just keep the original ID.
     310                 :            :         // ip->ip_id = NextIP_ID(ip->ip_src.s_addr, ip->ip_id);
     311                 :            : 
     312         [ #  # ]:          0 :         ASSERT((tcp_offset - ip_offset) % 4 == 0);
     313                 :          0 :         ip->ip_hl = (tcp_offset - ip_offset) >> 2;
     314                 :          0 :         ip->ip_len = htons(buffer_offset - ip_offset);
     315                 :          0 :         ip->ip_off = 0;              // DF = 0, MF = 0, offset = 0
     316                 :          0 :         ip->ip_sum = 0;
     317                 :          0 :         ip->ip_sum = 0xffff - ones_complement_checksum((const void*) ip, tcp_offset - ip_offset, 0);
     318                 :            : 
     319                 :            :         // Link level header:
     320                 :            :         // Question: what to do with the link level header? Currently we just
     321                 :            :         // keep the original header, even though the length field can
     322                 :            :         // be incorrect. ###
     323                 :            : 
     324         [ #  # ]:          0 :         if ( timestamp < trace_rewriter->RewritePacket()->TimeStamp() )
     325                 :            :                 // For out of order rewriting.
     326                 :          0 :                 timestamp = trace_rewriter->RewritePacket()->TimeStamp();
     327                 :            : 
     328                 :            :         // The below works around a potential type incompatibility
     329                 :            :         // on systems where pcap's timeval is different from the
     330                 :            :         // system-wide one. --cpk
     331                 :            :         //
     332                 :          0 :         timeval tv_tmp = double_to_timeval(timestamp);
     333                 :          0 :         pcap_hdr.ts.tv_sec = tv_tmp.tv_sec;
     334                 :          0 :         pcap_hdr.ts.tv_usec = tv_tmp.tv_usec;
     335                 :          0 :         pcap_hdr.caplen = pcap_hdr.len = buffer_offset;
     336                 :            : 
     337                 :          0 :         hdr = &pcap_hdr;
     338                 :          0 :         arg_pkt = pkt;
     339                 :          0 :         length = buffer_offset;
     340                 :            : 
     341                 :          0 :         return 1;
     342                 :            :         }
     343                 :            : 
     344                 :          0 : void TCP_TracePacket::Reuse()
     345                 :            :         {
     346                 :          0 :         reuse = 1;
     347                 :            : 
     348                 :          0 :         timestamp = trace_rewriter->RewritePacket()->TimeStamp();
     349                 :            : 
     350                 :            :         // Question 1: Shall we keep TCP options in the header? Note
     351                 :            :         // that the TCP header of a packet is sometimes replicated in
     352                 :            :         // the rewritten trace (because we reuse headers). When an
     353                 :            :         // option have idempotent semantics, it is safe to keep the
     354                 :            :         // option; otherwise we should include the option only in the
     355                 :            :         // first one among replicated copies. Currently we keep
     356                 :            :         // options for simplicity and wait for things to happen. ###
     357                 :            : 
     358                 :          0 :         struct tcphdr* tp = (struct tcphdr*) (pkt + tcp_offset);
     359                 :          0 :         tp->th_flags = 0;
     360                 :            : 
     361                 :            :         // Clear all TCP options.
     362                 :          0 :         unsigned int prev_data_offset = data_offset;
     363                 :          0 :         buffer_offset = data_offset = tcp_offset + sizeof(struct tcphdr);
     364         [ #  # ]:          0 :         if ( prev_data_offset - tcp_offset > sizeof(*tp) )
     365                 :            :                 TCP_Analyzer::ParseTCPOptions(tp,
     366                 :            :                                         TCP_Rewriter::RewriteTCPOption,
     367                 :          0 :                                         trace_rewriter->Analyzer(), is_orig, this);
     368                 :          0 :         }
     369                 :            : 
     370                 :          0 : RecordVal* TCP_TracePacket::PacketVal()
     371                 :            :         {
     372         [ #  # ]:          0 :         if ( ! packet_val )
     373                 :            :                 {
     374                 :          0 :                 packet_val = new RecordVal(packet_type);
     375                 :          0 :                 packet_val->Assign(0, TraceRewriter()->Analyzer()->BuildConnVal());
     376                 :          0 :                 packet_val->Assign(1, new Val(IsOrig(), TYPE_BOOL));
     377                 :          0 :                 packet_val->Assign(2, new Val(PacketSeq(), TYPE_COUNT));
     378                 :          0 :                 packet_val->Assign(3, new Val(TimeStamp(), TYPE_TIME));
     379                 :          0 :                 packet_val->SetOrigin(this);
     380                 :            :                 }
     381                 :            :         else
     382                 :          0 :                 Ref(packet_val);
     383                 :            : 
     384                 :          0 :         return packet_val;
     385                 :            :         }
     386                 :            : 
     387                 :          0 : uint16 NextIP_ID(const uint32 src_addr, const uint16 id)
     388                 :            :         {
     389         [ #  # ]:          0 :         if ( ip_id_set == 0 )
     390                 :          0 :                 ip_id_set = new IP_IDSet();
     391                 :            : 
     392                 :            :         IP_ID ipid;
     393                 :          0 :         ipid.ip = src_addr;
     394                 :          0 :         ipid.id = id;
     395                 :            : 
     396         [ #  # ]:          0 :         while ( ip_id_set->find(ipid) != ip_id_set->end() )
     397                 :            :                 {
     398                 :          0 :                 ipid.id = (ipid.id + 1) & 0xffff;
     399                 :            : 
     400         [ #  # ]:          0 :                 if ( ipid.id == id )
     401                 :            :                         { // clear all entries of the IP
     402                 :            :                         IP_ID first_id, last_id;
     403                 :          0 :                         first_id.ip = last_id.ip = src_addr;
     404                 :          0 :                         first_id.id = 0; last_id.id = 0xffff;
     405                 :            :                         ip_id_set->erase(ip_id_set->find(first_id),
     406                 :          0 :                                                 ip_id_set->find(last_id));
     407                 :            :                         }
     408                 :            :                 }
     409                 :            : 
     410                 :          0 :         ip_id_set->insert(ipid);
     411                 :            : 
     412                 :          0 :         return uint16(ipid.id & 0xffff);
     413                 :            :         }
     414                 :            : 
     415                 :          0 : TCP_RewriterEndpoint::TCP_RewriterEndpoint(TCP_Rewriter* arg_rewriter)
     416                 :            :         {
     417                 :          0 :         rewriter = arg_rewriter;
     418                 :          0 :         next_packet = 0;
     419                 :          0 :         endp = 0;
     420                 :          0 :         established = 0;
     421                 :          0 :         end_of_data = 0;
     422                 :          0 :         peer = 0;
     423                 :          0 :         last_ack = 0;
     424                 :          0 :         last_packet_time = -1;
     425                 :          0 :         please_flush = 0;
     426                 :          0 :         flushed = 1;
     427                 :          0 :         flush_scheduled = 0;
     428                 :          0 :         there_is_a_gap = 0;
     429                 :          0 :         }
     430                 :            : 
     431                 :          0 : TCP_RewriterEndpoint::~TCP_RewriterEndpoint()
     432                 :            :         {
     433 [ #  # ][ #  # ]:          0 :         if ( ! prolog.empty() )
     434                 :            :                 {
     435 [ #  # ][ #  # ]:          0 :                 if ( ! next_packet )
     436                 :          0 :                         Weird(MSG_PREFIX "end point has data, but hasn't got any packet till destruction.");
     437                 :            :                 else
     438                 :          0 :                         internal_error(MSG_PREFIX "prolog should've been purged on the very first packet.");
     439                 :            : 
     440 [ #  # ][ #  # ]:          0 :                 while ( ! prolog.empty() )
     441                 :            :                         {
     442 [ #  # ][ #  # ]:          0 :                         delete prolog.front();
     443                 :          0 :                         prolog.pop();
     444                 :            :                         }
     445                 :            :                 }
     446                 :            : 
     447 [ #  # ][ #  # ]:          0 :         if ( ! end_of_data && next_packet && ! next_packet->IsEmpty() )
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
     448                 :            :                 Weird(fmt(MSG_PREFIX "end of data missing before deleting the connection: %.6f",
     449                 :          0 :                           next_packet->TimeStamp()));
     450                 :            : 
     451 [ #  # ][ #  # ]:          0 :         if ( next_packet )
     452                 :          0 :                 Unref(next_packet);
     453                 :          0 :         }
     454                 :            : 
     455                 :          0 : void TCP_RewriterEndpoint::Init()
     456                 :            :         {
     457                 :            :         // This cannot be put into the constructor because it requires
     458                 :            :         // existence of the peer.
     459                 :          0 :         peer = rewriter->GetPeer(this);
     460                 :          0 :         }
     461                 :            : 
     462                 :            : // NextPacket sets 'ticks' of packet dumping according to packet
     463                 :            : // arrival in the original sequence.
     464                 :          0 : void TCP_RewriterEndpoint::NextPacket(TCP_TracePacket* p)
     465                 :            :         {
     466                 :          0 :         please_flush = 1;
     467                 :          0 :         flushed = 0;
     468                 :          0 :         last_packet_time = p->TimeStamp();
     469                 :            : 
     470         [ #  # ]:          0 :         if ( ! endp )
     471                 :          0 :                 endp = rewriter->GetEndpoint(this);
     472                 :            : 
     473         [ #  # ]:          0 :         if ( endp->state == TCP_ENDPOINT_ESTABLISHED )
     474                 :          0 :                 established = 1;
     475                 :            : 
     476 [ #  # ][ #  # ]:          0 :         if ( ! next_packet || p->GetTCP_Flag(TH_SYN) )
                 [ #  # ]
     477                 :            :                 {
     478 [ #  # ][ #  # ]:          0 :                 if ( ! p->GetTCP_Flag(TH_SYN | TH_RST) &&
                 [ #  # ]
     479                 :            :                      ! rewriter->Analyzer()->IsPartial() )
     480                 :          0 :                         Weird(MSG_PREFIX "first packet is not SYN or RST");
     481                 :            : 
     482                 :          0 :                 start_seq = next_seq = p->GetSeq();
     483                 :            :                 }
     484                 :            : 
     485                 :          0 :         SetNextPacket(p);
     486                 :          0 :         ScheduleFlush();
     487                 :          0 :         }
     488                 :            : 
     489                 :          0 : void TCP_RewriterEndpoint::WriteData(int len, const u_char* data)
     490                 :            :         {
     491         [ #  # ]:          0 :         if ( end_of_data & (END_BY_FIN | END_BY_RST) )
     492                 :          0 :                 Weird(MSG_PREFIX "write after end of data");
     493                 :            : 
     494         [ #  # ]:          0 :         if ( ! next_packet )
     495                 :            :                 {
     496                 :            :                 // Till anybody really wants to use the prolog ...
     497                 :          0 :                 run_time(fmt("pushing %d bytes into prolog", len));
     498                 :          0 :                 prolog.push(new BroString(data, len, 0));
     499                 :            :                 }
     500                 :            :         else
     501                 :            :                 {
     502                 :            :                 // Originally we did not send data along with SYN or RST.
     503                 :            :                 // if ( next_packet->GetTCP_Flag(TH_SYN | TH_RST) )
     504                 :            :                 //      internal_error("SYN/RST packet not immediately flushed");
     505                 :            : 
     506                 :            :                 // Question: shall we send data along with the ACK in the
     507                 :            :                 // connection's three way handshake? Here it may do so.
     508                 :            : 
     509                 :          0 :                 DoWriteData(len, data);
     510                 :            : 
     511         [ #  # ]:          0 :                 if ( please_flush )
     512                 :          0 :                         ScheduleFlush();
     513                 :            :                 }
     514                 :          0 :         }
     515                 :            : 
     516                 :          0 : void TCP_RewriterEndpoint::SkipGap(int len)
     517                 :            :         {
     518                 :          0 :         next_seq += len;
     519                 :          0 :         there_is_a_gap = 1;
     520                 :            : 
     521         [ #  # ]:          0 :         if ( next_packet )
     522                 :          0 :                 next_packet->SetSeqGap(0);
     523                 :          0 :         }
     524                 :            : 
     525                 :          0 : void TCP_RewriterEndpoint::Push()
     526                 :            :         {
     527         [ #  # ]:          0 :         if ( ! next_packet )
     528                 :          0 :                 return;
     529                 :            : 
     530                 :          0 :         next_packet->SetTCP_Flag(TH_PUSH, 1);
     531                 :          0 :         PushPacket();
     532                 :            :         }
     533                 :            : 
     534                 :          0 : void TCP_RewriterEndpoint::ReqAck()
     535                 :            :         {
     536         [ #  # ]:          0 :         if ( ! next_packet )
     537                 :          0 :                 return;
     538                 :            : 
     539                 :          0 :         PushPacket();
     540                 :            :         }
     541                 :            : 
     542                 :          0 : void TCP_RewriterEndpoint::Flush()
     543                 :            :         {
     544 [ #  # ][ #  # ]:          0 :         if ( ! next_packet || next_packet->OnHold() )
                 [ #  # ]
     545                 :            :                 // This may happen after the code change in
     546                 :            :                 // TCP_Connection::NextPacket -- not every packet
     547                 :            :                 // reaches the TCP rewriter.  Also, do not dump a packet
     548                 :            :                 // on hold -- the packet will be flushed later.
     549                 :            :                 // internal_error(MSG_PREFIX "flush before packet arrival");
     550                 :          0 :                 return;
     551                 :            : 
     552                 :            :         DEBUG_MSG_A("preparing to flush packet %d (%.6f)\n", next_packet->PacketSeq(), next_packet->TimeStamp());
     553         [ #  # ]:          0 :         if ( next_packet->FINScheduled() )
     554                 :          0 :                 GenerateFIN();
     555                 :            : 
     556         [ #  # ]:          0 :         if ( please_flush )
     557                 :            :                 {
     558                 :            :                 DEBUG_MSG_A("Flush packet %d (%.6f)\n", next_packet->PacketSeq(), next_packet->TimeStamp());
     559                 :          0 :                 PushPacket();
     560                 :            :                 }
     561                 :            : 
     562         [ #  # ]:          0 :         if ( ! next_packet->IsEmpty() )
     563                 :            :                 {
     564                 :          0 :                 internal_error(MSG_PREFIX "packet is not empty after flushing");
     565                 :            :                 }
     566                 :            : 
     567                 :          0 :         flush_scheduled = 0;
     568                 :            :         }
     569                 :            : 
     570                 :          0 : void TCP_RewriterEndpoint::ScheduleFlush()
     571                 :            :         {
     572         [ #  # ]:          0 :         if ( ! flush_scheduled )
     573                 :            :                 {
     574                 :          0 :                 schedule_flush(this);
     575                 :          0 :                 flush_scheduled = 1;
     576                 :            :                 DEBUG_MSG_A("%.6f flush scheduled for packet %d (%.6f)\n", network_time, next_packet->PacketSeq(), next_packet->TimeStamp());
     577                 :            :                 }
     578                 :          0 :         }
     579                 :            : 
     580                 :          0 : void TCP_RewriterEndpoint::GenerateFIN()
     581                 :            :         {
     582         [ #  # ]:          0 :         if ( end_of_data & END_BY_FIN )
     583                 :          0 :                 return;
     584                 :            : 
     585                 :            :         DEBUG_MSG_A("FIN at %.6f\n", next_packet->TimeStamp());
     586                 :          0 :         end_of_data |= END_BY_FIN;
     587                 :            : 
     588         [ #  # ]:          0 :         if ( ! next_packet )
     589                 :            :                 // Weird(MSG_PREFIX "FIN before packet arrival");
     590                 :          0 :                 internal_error(MSG_PREFIX "FIN before packet arrival");
     591                 :            :         else
     592                 :            :                 {
     593                 :          0 :                 next_packet->ScheduleFIN(0);
     594                 :          0 :                 next_packet->SetTCP_Flag(TH_FIN, 1);
     595                 :          0 :                 please_flush = 1;
     596                 :            :                 }
     597                 :            :         }
     598                 :            : 
     599                 :          0 : void TCP_RewriterEndpoint::Reset(int self)
     600                 :            :         {
     601                 :            :         DEBUG_MSG_A("%.6f end by RST (empty = %d)\n", network_time, next_packet ? next_packet->IsEmpty() : -1);
     602         [ #  # ]:          0 :         if ( self )
     603                 :          0 :                 end_of_data |= END_BY_RST;
     604                 :            :         else
     605                 :          0 :                 end_of_data |= END_BY_PEER_RST;
     606                 :          0 :         }
     607                 :            : 
     608                 :          0 : void TCP_RewriterEndpoint::SetNextPacket(TCP_TracePacket* p)
     609                 :            :         {
     610         [ #  # ]:          0 :         if ( next_packet )
     611                 :            :                 {
     612 [ #  # ][ #  # ]:          0 :                 if ( ! next_packet->IsEmpty() || next_packet->OnHold() )
                 [ #  # ]
     613                 :          0 :                         internal_error(MSG_PREFIX "next packet (%.6f) arrives before the previous packet (%.6f) is flushed", p->TimeStamp(), next_packet->TimeStamp());
     614                 :            :                         // PushPacket();
     615                 :            : 
     616                 :          0 :                 Unref(next_packet);
     617                 :            :                 }
     618                 :            : 
     619                 :          0 :         next_packet = p;
     620                 :            : 
     621         [ #  # ]:          0 :         if ( next_packet->SeqGap() > 0 )
     622                 :          0 :                 peer->SkipGap(next_packet->SeqGap());
     623                 :            : 
     624                 :            :         // next_packet->SetTCP_Flag(TH_PUSH, 0);
     625                 :            : 
     626                 :            :         // Do not send FIN at this moment because FIN may arrive out
     627                 :            :         // of order -- wait till all contents are delivered
     628                 :          0 :         next_packet->SetTCP_Flag(TH_FIN, 0);
     629                 :            : 
     630         [ #  # ]:          0 :         if ( ! prolog.empty() )
     631                 :            :                 {
     632                 :            :                 // Do not put prolog into SYN/RST packets
     633         [ #  # ]:          0 :                 if ( next_packet->GetTCP_Flag(TH_SYN | TH_RST) )
     634                 :          0 :                         PushPacket();
     635                 :          0 :                 PurgeProlog();
     636                 :            :                 }
     637                 :          0 :         }
     638                 :            : 
     639                 :          0 : void TCP_RewriterEndpoint::PurgeProlog()
     640                 :            :         {
     641         [ #  # ]:          0 :         while ( ! prolog.empty() )
     642                 :            :                 {
     643                 :          0 :                 BroString* s = prolog.front();
     644                 :          0 :                 WriteData(s->Len(), s->Bytes());
     645                 :          0 :                 prolog.pop();
     646         [ #  # ]:          0 :                 delete s;
     647                 :            :                 }
     648                 :          0 :         }
     649                 :            : 
     650                 :          0 : void TCP_RewriterEndpoint::DoWriteData(int len, const u_char* data)
     651                 :            :         {
     652         [ #  # ]:          0 :         ASSERT(next_packet);
     653                 :            : 
     654         [ #  # ]:          0 :         while ( len > 0 )
     655                 :            :                 {
     656                 :          0 :                 int left = next_packet->Space();
     657                 :            : 
     658         [ #  # ]:          0 :                 if ( ! left )
     659                 :            :                         {
     660                 :          0 :                         PushPacket();
     661                 :          0 :                         left = next_packet->Space();
     662                 :            :                         }
     663                 :            : 
     664         [ #  # ]:          0 :                 if ( left > len )
     665                 :          0 :                         left = len;
     666                 :            : 
     667         [ #  # ]:          0 :                 if ( ! next_packet->AppendData(data, left) )
     668                 :          0 :                         ASSERT(0);
     669                 :            : 
     670                 :          0 :                 data += left;
     671                 :          0 :                 len -= left;
     672                 :          0 :                 please_flush = 1;
     673                 :            :                 }
     674                 :          0 :         }
     675                 :            : 
     676                 :          0 : int TCP_RewriterEndpoint::IsPlaceHolderPacket(TCP_TracePacket* p)
     677                 :            :         {
     678                 :            :         return p->SeqLength() == 0 &&
     679                 :            :                ! p->GetTCP_Flag(TH_SYN | TH_RST | TH_FIN | TH_URG ) &&
     680 [ #  # ][ #  # ]:          0 :                ! (p->GetTCP_Flag(TH_ACK) && p->GetAck() > last_ack);
         [ #  # ][ #  # ]
     681                 :            :         }
     682                 :            : 
     683                 :          0 : void TCP_RewriterEndpoint::PushPacket()
     684                 :            :         {
     685         [ #  # ]:          0 :         if ( ! next_packet )
     686                 :            :                 {
     687                 :          0 :                 internal_error(MSG_PREFIX "cannot push packet before packet arrival");
     688                 :            :                 return;
     689                 :            :                 }
     690                 :            : 
     691                 :            :         // Set sequence number ...
     692                 :          0 :         next_packet->SetSeq(next_seq);
     693                 :          0 :         int seq_len = next_packet->SeqLength();
     694                 :            : 
     695                 :          0 :         next_seq += seq_len;
     696                 :            : 
     697                 :            :         // ... and acknowledge peer's recently dumped packet.
     698   [ #  #  #  # ]:          0 :         if ( next_packet->GetTCP_Flag(TH_SYN | TH_RST) &&
                 [ #  # ]
     699                 :            :              ! next_packet->GetTCP_Flag(TH_ACK) )
     700                 :            :                 {
     701                 :          0 :                 next_packet->SetTCP_Flag(TH_ACK, 0);
     702                 :          0 :                 next_packet->SetAck(0);
     703                 :            :                 }
     704                 :            :         else
     705                 :            :                 {
     706                 :          0 :                 next_packet->SetTCP_Flag(TH_ACK, 1);
     707         [ #  # ]:          0 :                 if ( peer->HasPacket() )
     708                 :          0 :                         next_packet->SetAck(peer->NextSeq());
     709                 :            :                 }
     710                 :            : 
     711                 :          0 :         int RST = next_packet->GetTCP_Flag(TH_RST);
     712                 :            : 
     713                 :            : #if 0
     714                 :            :         // With the feature of reserve_rewrite_slot, packet dumping can
     715                 :            :         // be delayed.
     716                 :            : 
     717                 :            :         // Enforce the order of timestamps; but delayed FIN is OK
     718                 :            :         // when there is a gap.
     719                 :            :         if ( next_packet->TimeStamp() < network_time &&
     720                 :            :              ! (next_packet->GetTCP_Flag(TH_FIN) && there_is_a_gap) )
     721                 :            :                 {
     722                 :            :                 Weird(MSG_PREFIX "delayed packet");
     723                 :            :                 Weird(fmt(MSG_PREFIX "packet time %.6f, dumping time %.6f\n",
     724                 :            :                          next_packet->TimeStamp(), network_time));
     725                 :            :                 }
     726                 :            : #endif
     727                 :            : 
     728   [ #  #  #  # ]:          0 :         if ( ! IsPlaceHolderPacket(next_packet) ||
                 [ #  # ]
     729                 :            :              ! omit_rewrite_place_holder )
     730                 :            :                 {
     731         [ #  # ]:          0 :                 if ( next_packet->PredictedAsEmptyPlaceHolder() )
     732                 :            :                         {
     733 [ #  # ][ #  # ]:          0 :                         DEBUG_MSG("The packet to dump (%.6f, %d, %d, %s%s%s%s, %u > %u) was predicted to be an empty place holder.",
         [ #  # ][ #  # ]
     734                 :            :                                 next_packet->TimeStamp(), next_packet->SeqLength(), next_packet->PayloadLength(),
     735                 :            :                                 next_packet->GetTCP_Flag(TH_SYN) ? "S" : "",
     736                 :            :                                 next_packet->GetTCP_Flag(TH_RST) ? "R" : "",
     737                 :            :                                 next_packet->GetTCP_Flag(TH_FIN) ? "F" : "",
     738                 :            :                                 next_packet->GetTCP_Flag(TH_URG) ? "U" : "",
     739                 :            :                                 next_packet->GetAck(), last_ack);
     740                 :            :                         }
     741                 :            : 
     742                 :          0 :                 rewriter->DumpPacket(this, next_packet);
     743                 :            :                 }
     744                 :            : 
     745 [ #  # ][ #  # ]:          0 :         if ( next_packet->GetTCP_Flag(TH_ACK) &&
                 [ #  # ]
     746                 :            :              next_packet->GetAck() > last_ack )
     747                 :          0 :                 last_ack = next_packet->GetAck();
     748                 :            : 
     749                 :            :         // Reuse the packet headers.
     750                 :          0 :         next_packet->Reuse();
     751                 :            : 
     752         [ #  # ]:          0 :         if ( ! next_packet->FINScheduled() )
     753                 :            :                 {
     754                 :          0 :                 please_flush = 0;
     755         [ #  # ]:          0 :                 if ( ! next_packet->IsEmpty() )
     756                 :          0 :                         internal_error("should have been cleared");
     757                 :            :                 }
     758                 :            : 
     759         [ #  # ]:          0 :         if ( RST )
     760                 :            :                 {
     761                 :          0 :                 Reset(1);       // itself ...
     762                 :          0 :                 peer->Reset(0); // ... and peer
     763                 :          0 :                 return;
     764                 :            :                 }
     765                 :            : 
     766                 :            :         // Question: do we need to request an ACK? Yes, if the packet
     767                 :            :         // is an artificially generated packet.
     768 [ #  # ][ #  # ]:          0 :         if ( seq_len > 0 &&
                 [ #  # ]
     769                 :            :              next_packet->TimeStamp() < rewriter->RewritePacket()->TimeStamp() )
     770                 :          0 :                 peer->ReqAck();
     771                 :            :         }
     772                 :            : 
     773                 :          0 : void TCP_RewriterEndpoint::Weird(const char* name) const
     774                 :            :         {
     775                 :            : #ifdef DEBUG_BRO
     776                 :            :         rewriter->Weird(name);
     777                 :            : #endif
     778                 :          0 :         }
     779                 :            : 
     780                 :            : TCP_Rewriter::TCP_Rewriter(TCP_Analyzer* arg_analyzer, PacketDumper* arg_dumper,
     781                 :          0 :                                 int arg_MTU, int arg_wait_for_commitment)
     782                 :            :         {
     783                 :          0 :         analyzer = arg_analyzer;
     784                 :          0 :         dumper = arg_dumper;
     785                 :          0 :         MTU = arg_MTU;
     786                 :          0 :         wait_for_commitment = arg_wait_for_commitment;
     787                 :          0 :         discard_packets = 0;    // till AbortPackets(1);
     788                 :            : 
     789                 :          0 :         packets_rewritten = 0;
     790                 :          0 :         next_packet_seq = 0;
     791                 :          0 :         pending_content_gap = 0;
     792                 :            : 
     793                 :          0 :         orig = new TCP_RewriterEndpoint(this);
     794                 :          0 :         resp = new TCP_RewriterEndpoint(this);
     795                 :            : 
     796                 :          0 :         orig->Init();
     797                 :          0 :         resp->Init();
     798                 :            : 
     799                 :          0 :         anon_addr[0] = anon_addr[1] = 0;
     800                 :            : 
     801   [ #  #  #  # ]:          0 :         if ( anonymize_ip_addr )
     802                 :            :                 {
     803                 :            :                 anon_addr[0] = anonymize_ip(to_v4_addr(analyzer->Conn()->OrigAddr()),
     804                 :          0 :                                                 ORIG_ADDR);
     805                 :            :                 anon_addr[1] = anonymize_ip(to_v4_addr(analyzer->Conn()->RespAddr()),
     806                 :          0 :                                                 RESP_ADDR);
     807                 :            :                 }
     808                 :            : 
     809                 :          0 :         holding_packets = 0;
     810                 :          0 :         current_packet = next_packet = 0;
     811                 :            : 
     812                 :          0 :         current_slot = first_slot = last_slot = 0;
     813                 :          0 :         highest_slot_number = 0;
     814                 :          0 :         answered[0] = answered[1] = 0;
     815                 :          0 :         }
     816                 :            : 
     817                 :          0 : void TCP_Rewriter::Done()
     818                 :            :         {
     819                 :            :         // The wrap-up work needs to be done *after* event processing,
     820                 :            :         // therefore we schedule a funeral to be held right before
     821                 :            :         // packets are flushed.
     822                 :          0 :         schedule_funeral(this);
     823                 :          0 :         }
     824                 :            : 
     825                 :          0 : void TCP_Rewriter::Funeral()
     826                 :            :         {
     827         [ #  # ]:          0 :         if ( ! uncommited_packet_queue.empty() )
     828                 :            :                 {
     829                 :            :                 warn(fmt(MSG_PREFIX
     830                 :            :                          "rewriter gets neither commit or abort, "
     831                 :            :                          "and %d packets will be discarded",
     832                 :          0 :                          int(uncommited_packet_queue.size())));
     833                 :          0 :                 AbortPackets(0);
     834                 :            :                 }
     835                 :            : 
     836         [ #  # ]:          0 :         if ( ! slot_queue.empty() )
     837                 :            :                 {
     838                 :          0 :                 run_time("reserved slots are not completely released at the end of rewriter %s", analyzer->Conn());
     839         [ #  # ]:          0 :                 for ( slot_map_t::iterator it = reserved_slots.begin();
     840                 :            :                         it != reserved_slots.end();
     841                 :            :                         ++it )
     842                 :            :                         {
     843                 :          0 :                         TCP_RewriteSlot* slot = it->second;
     844                 :          0 :                         run_time(fmt("unreleased slot: %d", slot->Number()));
     845                 :            :                         }
     846                 :            : 
     847         [ #  # ]:          0 :                 while ( ! slot_queue.empty() )
     848                 :            :                         {
     849                 :          0 :                         TCP_RewriteSlot* slot = slot_queue.front();
     850                 :          0 :                         slot_queue.pop_front();
     851                 :          0 :                         slot->Dump();
     852         [ #  # ]:          0 :                         delete slot;
     853                 :            :                         }
     854                 :            : 
     855                 :          0 :                 reserved_slots.clear();
     856                 :          0 :                 ReleasePacketsOnHold();
     857                 :            :                 }
     858                 :            : 
     859         [ #  # ]:          0 :         if ( ! packets_on_hold.empty() )
     860                 :            :                 {
     861                 :          0 :                 run_time("packets on hold at the end of rewriter %s", analyzer->Conn());
     862                 :          0 :                 ReleasePacketsOnHold();
     863                 :            :                 // And release the last one.
     864                 :          0 :                 Endp(next_packet->IsOrig())->Flush();
     865                 :            :                 }
     866                 :          0 :         }
     867                 :            : 
     868                 :          0 : TCP_Rewriter::~TCP_Rewriter()
     869                 :            :         {
     870 [ #  # ][ #  # ]:          0 :         delete orig;
                 [ #  # ]
     871 [ #  # ][ #  # ]:          0 :         delete resp;
                 [ #  # ]
     872 [ #  # ][ #  # ]:          0 :         }
                 [ #  # ]
     873                 :            : 
     874                 :            : void TCP_Rewriter::NextPacket(int is_orig, double t,
     875                 :            :                               const struct pcap_pkthdr* pcap_hdr,
     876                 :            :                               const u_char* pcap_pkt, int hdr_size,
     877                 :            :                               const struct ip* ip,
     878                 :          0 :                               const struct tcphdr* tp)
     879                 :            :         {
     880                 :          0 :         unsigned int ip_hdr_len = ip->ip_hl * 4;
     881                 :          0 :         unsigned int tcp_hdr_len = tp->th_off * 4;
     882                 :            : 
     883                 :            :         TCP_TracePacket* p =
     884                 :            :                 new TCP_TracePacket(this, ++next_packet_seq, t,
     885                 :            :                                         is_orig, pcap_hdr, MTU,
     886                 :          0 :                                         hdr_size + ip_hdr_len + tcp_hdr_len);
     887                 :            : 
     888         [ #  # ]:          0 :         if ( ! p->AppendLinkHeader(pcap_pkt, hdr_size) )
     889                 :          0 :                 internal_error(MSG_PREFIX "cannot append headers -- check MTU");
     890                 :            : 
     891         [ #  # ]:          0 :         if ( ! p->AppendIPHeader((const u_char*)ip, sizeof(*ip)) )
     892                 :          0 :                 internal_error(MSG_PREFIX "cannot append headers -- check MTU");
     893                 :            : 
     894                 :            :         if ( ip_hdr_len > sizeof(*ip) )
     895                 :            :                 {
     896                 :            :                 // TODO: re-write IP options.
     897                 :            :                 }
     898                 :            : 
     899         [ #  # ]:          0 :         if ( ! p->AppendTCPHeader((const u_char*)tp, sizeof(*tp)) )
     900                 :          0 :                 internal_error(MSG_PREFIX "cannot append headers -- check MTU");
     901                 :            : 
     902                 :            :         // Rewrite TCP options.
     903         [ #  # ]:          0 :         if ( tcp_hdr_len > sizeof(*tp) )
     904                 :            :                 TCP_Analyzer::ParseTCPOptions(tp, RewriteTCPOption,
     905                 :          0 :                                                 analyzer, is_orig, p);
     906                 :            : 
     907                 :            :         // Pad the TCP header.
     908                 :          0 :         p->AppendData(0, 0);
     909                 :            : 
     910                 :            :         // Before setting current_packet to p, first clean up empty
     911                 :            :         // place holders to save memory space.
     912   [ #  #  #  # ]:          0 :         if ( omit_rewrite_place_holder && holding_packets )
     913                 :          0 :                 CleanUpEmptyPlaceHolders();
     914                 :            : 
     915                 :          0 :         current_packet = p;
     916                 :            : 
     917         [ #  # ]:          0 :         if ( pending_content_gap )
     918                 :            :                 {
     919                 :            :                 // A packet triggers a content gap only in the other
     920                 :            :                 // direction.
     921         [ #  # ]:          0 :                 if ( current_packet->IsOrig() )
     922                 :          0 :                         pending_content_gap = -pending_content_gap;
     923                 :            : 
     924         [ #  # ]:          0 :                 if ( pending_content_gap < 0 )
     925                 :          0 :                         internal_error("content gap out of sync with packet");
     926                 :            : 
     927                 :          0 :                 current_packet->SetSeqGap(pending_content_gap);
     928                 :          0 :                 pending_content_gap = 0;
     929                 :            :                 }
     930                 :            : 
     931         [ #  # ]:          0 :         if ( current_slot )
     932                 :          0 :                 add_slot();
     933                 :            : 
     934         [ #  # ]:          0 :         if ( ! holding_packets )
     935                 :            :                 {
     936                 :          0 :                 next_packet = p;
     937                 :          0 :                 Endp(is_orig)->NextPacket(p);
     938                 :            :                 }
     939                 :            :         else
     940                 :            :                 {
     941                 :            :                 DEBUG_MSG_A("packet %d (%.6f) on hold\n",
     942                 :            :                                 p->PacketSeq(), p->TimeStamp());
     943                 :          0 :                 packets_on_hold.push_back(p);
     944                 :          0 :                 ++num_packets_held;
     945                 :            :                 }
     946                 :          0 :         }
     947                 :            : 
     948                 :          0 : void TCP_Rewriter::ContentGap(int is_orig, int len)
     949                 :            :         {
     950         [ #  # ]:          0 :         if ( is_orig )
     951                 :          0 :                 pending_content_gap = len;
     952                 :            :         else
     953                 :          0 :                 pending_content_gap = -len;
     954                 :          0 :         }
     955                 :            : 
     956                 :          0 : void TCP_Rewriter::ScheduleFIN(int is_orig)
     957                 :            :         {
     958 [ #  # ][ #  # ]:          0 :         if ( current_packet && current_packet->IsOrig() == is_orig )
                 [ #  # ]
     959                 :          0 :                 current_packet->ScheduleFIN();
     960                 :            : 
     961                 :            :         // Otherwise just ignore the FIN.
     962                 :            :         // Endp(is_orig)->ScheduleFIN();
     963                 :          0 :         }
     964                 :            : 
     965                 :          0 : void TCP_Rewriter::WriteData(int is_orig, int len, const u_char* data)
     966                 :            :         {
     967         [ #  # ]:          0 :         if ( ! current_slot )
     968                 :          0 :                 DoWriteData(is_orig, len, data);
     969                 :            :         else
     970                 :          0 :                 current_slot->WriteData(is_orig, len, data);
     971                 :          0 :         }
     972                 :            : 
     973                 :          0 : void TCP_Rewriter::DoWriteData(int is_orig, int len, const u_char* data)
     974                 :            :         {
     975                 :          0 :         if ( is_orig != next_packet->IsOrig() )
     976                 :            :                 {
     977                 :            :                 // Weird(fmt("%.6f rewriting packet on the opposite direction", network_time));
     978                 :            :                 }
     979                 :            : 
     980                 :          0 :         Endp(is_orig)->WriteData(len, data);
     981                 :          0 :         }
     982                 :            : 
     983                 :          0 : void TCP_Rewriter::Push(int is_orig)
     984                 :            :         {
     985                 :          0 :         Endp(is_orig)->Push();
     986                 :          0 :         }
     987                 :            : 
     988                 :          0 : void TCP_Rewriter::DumpPacket(TCP_RewriterEndpoint* endp, TCP_TracePacket* p)
     989                 :            :         {
     990                 :            :         struct pcap_pkthdr* hdr;
     991                 :            :         const u_char* pkt;
     992                 :            :         int length;
     993                 :            :         ipaddr32_t anon_src, anon_dst;          // anonymized IP addresses
     994                 :            : 
     995         [ #  # ]:          0 :         if ( discard_packets )
     996                 :          0 :                 return;
     997                 :            : 
     998         [ #  # ]:          0 :         if ( endp == orig )
     999                 :            :                 {
    1000                 :          0 :                 anon_src = anon_addr[0];
    1001                 :          0 :                 anon_dst = anon_addr[1];
    1002                 :            :                 }
    1003                 :            :         else
    1004                 :            :                 {
    1005                 :          0 :                 anon_src = anon_addr[1];
    1006                 :          0 :                 anon_dst = anon_addr[0];
    1007                 :            :                 }
    1008                 :            : 
    1009         [ #  # ]:          0 :         if ( p->Finish(hdr, pkt, length, anon_src, anon_dst) )
    1010                 :            :                 {
    1011                 :            :                 DEBUG_MSG_A("Packet %d (%.6f) dumped at %.6f\n", p->PacketSeq(), p->TimeStamp(), network_time);
    1012                 :          0 :                 ++packets_rewritten;
    1013                 :            : 
    1014         [ #  # ]:          0 :                 if ( ! wait_for_commitment )
    1015                 :          0 :                         dumper->DumpPacket(hdr, pkt, length);
    1016                 :            :                 else
    1017                 :            :                         {
    1018                 :          0 :                         char* b = new char[sizeof(struct pcap_pkthdr) + length];
    1019                 :          0 :                         uncommited_packet_queue.push(b);
    1020                 :            : 
    1021                 :          0 :                         memcpy(b, hdr, sizeof(struct pcap_pkthdr));
    1022                 :            : 
    1023                 :          0 :                         b += sizeof(struct pcap_pkthdr);
    1024                 :          0 :                         memcpy(b, pkt, length);
    1025                 :            :                         }
    1026                 :            :                 }
    1027                 :            :         else
    1028                 :          0 :                 internal_error(MSG_PREFIX "ill formed packet for dumping");
    1029                 :            :         }
    1030                 :            : 
    1031                 :          0 : void TCP_Rewriter::ReleaseNextPacket()
    1032                 :            :         {
    1033         [ #  # ]:          0 :         if ( packets_on_hold.empty() )
    1034                 :            :                 {
    1035                 :          0 :                 internal_error("there is no packet on hold to release");
    1036                 :            :                 return;
    1037                 :            :                 }
    1038                 :            : 
    1039                 :          0 :         next_packet->SetOnHold(0);
    1040                 :          0 :         Endp(next_packet->IsOrig())->Flush();
    1041                 :          0 :         packets_on_hold.pop_front();
    1042                 :            : 
    1043         [ #  # ]:          0 :         if ( ! packets_on_hold.empty() )
    1044                 :            :                 {
    1045                 :          0 :                 next_packet = packets_on_hold.front();
    1046                 :          0 :                 Endp(next_packet->IsOrig())->NextPacket(next_packet);
    1047                 :            :                 }
    1048                 :            :         else
    1049                 :          0 :                 next_packet = 0;
    1050                 :            :         }
    1051                 :            : 
    1052                 :          0 : void TCP_Rewriter::HoldPacket(TCP_TracePacket* p)
    1053                 :            :         {
    1054         [ #  # ]:          0 :         if ( ! next_packet )
    1055                 :            :                 {
    1056                 :          0 :                 internal_error("should not try to hold a packet before packet arrival");
    1057                 :            :                 return;
    1058                 :            :                 }
    1059                 :            : 
    1060                 :          0 :         holding_packets = 1;
    1061                 :            : 
    1062 [ #  # ][ #  # ]:          0 :         while ( next_packet && next_packet->PacketSeq() < p->PacketSeq() )
                 [ #  # ]
    1063                 :          0 :                 ReleaseNextPacket();
    1064                 :            : 
    1065 [ #  # ][ #  # ]:          0 :         if ( ! next_packet ||
                 [ #  # ]
    1066                 :            :              next_packet->PacketSeq() != p->PacketSeq() )
    1067                 :            :                 {
    1068                 :            :                 internal_error("packet sequence not found for hold_packet: %d",
    1069                 :          0 :                     p->PacketSeq());
    1070                 :            :                 return;
    1071                 :            :                 }
    1072                 :            : 
    1073                 :          0 :         next_packet->SetOnHold(1);
    1074         [ #  # ]:          0 :         if ( packets_on_hold.empty() )
    1075                 :            :                 {
    1076                 :          0 :                 packets_on_hold.push_back(next_packet);
    1077                 :          0 :                 ++num_packets_held;
    1078                 :          0 :                 answered[0] = answered[1] = 0;
    1079                 :            :                 }
    1080                 :            :         }
    1081                 :            : 
    1082                 :          0 : void TCP_Rewriter::ReleasePacketsOnHold()
    1083                 :            :         {
    1084                 :          0 :         holding_packets = 0;
    1085         [ #  # ]:          0 :         if ( packets_on_hold.empty() )
    1086                 :          0 :                 return;
    1087                 :            : 
    1088         [ #  # ]:          0 :         while ( packets_on_hold.size() > 1 )
    1089                 :          0 :                 ReleaseNextPacket();
    1090                 :            : 
    1091                 :          0 :         next_packet->SetOnHold(0);
    1092                 :          0 :         packets_on_hold.pop_front();
    1093                 :            :         }
    1094                 :            : 
    1095                 :          0 : void TCP_Rewriter::AbortPackets(int apply_to_future)
    1096                 :            :         {
    1097         [ #  # ]:          0 :         while ( ! uncommited_packet_queue.empty() )
    1098                 :            :                 {
    1099                 :          0 :                 char* p = uncommited_packet_queue.front();
    1100                 :          0 :                 uncommited_packet_queue.pop();
    1101         [ #  # ]:          0 :                 delete [] p;
    1102                 :            :                 }
    1103                 :            : 
    1104         [ #  # ]:          0 :         if ( apply_to_future )
    1105                 :          0 :                 discard_packets = 1;
    1106                 :          0 :         }
    1107                 :            : 
    1108                 :          0 : void TCP_Rewriter::CommitPackets(int apply_to_future)
    1109                 :            :         {
    1110         [ #  # ]:          0 :         while ( ! uncommited_packet_queue.empty() )
    1111                 :            :                 {
    1112                 :            :                 struct pcap_pkthdr* hdr =
    1113                 :          0 :                         (struct pcap_pkthdr*) uncommited_packet_queue.front();
    1114                 :            : 
    1115                 :          0 :                 uncommited_packet_queue.pop();
    1116                 :            : 
    1117                 :            :                 dumper->DumpPacket(hdr,
    1118                 :            :                                 ((u_char*)hdr) + sizeof(struct pcap_pkthdr),
    1119                 :          0 :                                 int((hdr->caplen)));
    1120                 :            : 
    1121         [ #  # ]:          0 :                 delete [] (char*) hdr;
    1122                 :            :                 }
    1123                 :            : 
    1124         [ #  # ]:          0 :         if ( apply_to_future )
    1125                 :            :                 { // dump all future packets immediately
    1126                 :          0 :                 wait_for_commitment = 0;
    1127                 :          0 :                 discard_packets = 0;
    1128                 :            :                 }
    1129                 :          0 :         }
    1130                 :            : 
    1131                 :          0 : void TCP_Rewriter::CleanUpEmptyPlaceHolders()
    1132                 :            :         {
    1133         [ #  # ]:          0 :         if ( ! last_slot )
    1134                 :          0 :                 return;
    1135                 :            : 
    1136         [ #  # ]:          0 :         if ( last_slot->Packet() != current_packet )
    1137                 :          0 :                 internal_error("Mismatch: last_slot->packet != current_packet");
    1138                 :            : 
    1139 [ #  # ][ #  # ]:          0 :         if ( packets_on_hold.empty() ||
                 [ #  # ]
    1140                 :            :              packets_on_hold.back() != current_packet )
    1141                 :          0 :                 internal_error("Mismatch: packets_on_hold.back() != current_packet");
    1142                 :            : 
    1143         [ #  # ]:          0 :         int is_orig = current_packet->IsOrig() ? 1 : 0;
    1144                 :            : 
    1145         [ #  # ]:          0 :         if ( current_packet->SeqGap() > 0 )
    1146                 :            :                 // This packet signals a sequence gap (on the opposite flow).
    1147                 :          0 :                 answered[is_orig] = 0;
    1148                 :            : 
    1149                 :            :         // Is the current packet an empty placeholder packet?
    1150                 :            :         int current_packet_is_empty =
    1151                 :            :                 last_slot->isEmpty() &&
    1152                 :            :                 current_packet->SeqLength() == 0 &&
    1153                 :            :                 ! current_packet->GetTCP_Flag(TH_SYN|TH_RST|TH_FIN|TH_URG) &&
    1154 [ #  # ][ #  # ]:          0 :                 ! current_packet->HasReservedSlot();
         [ #  # ][ #  # ]
    1155                 :            : 
    1156         [ #  # ]:          0 :         if ( current_packet_is_empty )
    1157                 :            :                 {
    1158         [ #  # ]:          0 :                 if ( answered[is_orig] )
    1159                 :            :                         {
    1160                 :            : // #define DO_NOT_CLEAN_UP_ONLY_PREDICT
    1161                 :            : #ifdef DO_NOT_CLEAN_UP_ONLY_PREDICT
    1162                 :            :                         // for debugging
    1163                 :            :                         current_packet->PredictAsEmptyPlaceHolder();
    1164                 :            : #else
    1165                 :          0 :                         ++num_packets_cleaned;
    1166                 :          0 :                         packets_on_hold.pop_back();
    1167                 :          0 :                         Unref(current_packet);
    1168                 :          0 :                         current_packet = 0;
    1169                 :          0 :                         slot_queue.pop_back();
    1170         [ #  # ]:          0 :                         delete last_slot;
    1171                 :          0 :                         last_slot = slot_queue.back();
    1172                 :            : #endif
    1173                 :            :                         }
    1174                 :            :                 }
    1175                 :            :         else
    1176                 :            :                 // Current packet may not be empty ...
    1177                 :          0 :                 answered[1 - is_orig] = 0;
    1178                 :            : 
    1179                 :          0 :         answered[is_orig] = 1;
    1180                 :            :         }
    1181                 :            : 
    1182                 :          0 : int TCP_Rewriter::LeaveAddrInTheClear(int is_orig)
    1183                 :            :         {
    1184         [ #  # ]:          0 :         if ( packets_rewritten > 0 )
    1185                 :          0 :                 return 0;
    1186                 :            : 
    1187         [ #  # ]:          0 :         if ( is_orig )
    1188                 :          0 :                 anon_addr[0] = to_v4_addr(analyzer->Conn()->OrigAddr());
    1189                 :            :         else
    1190                 :          0 :                 anon_addr[1] = to_v4_addr(analyzer->Conn()->RespAddr());
    1191                 :            : 
    1192                 :          0 :         return 1;
    1193                 :            :         }
    1194                 :            : 
    1195                 :          0 : TCP_Endpoint* TCP_Rewriter::GetEndpoint(TCP_RewriterEndpoint* endp)
    1196                 :            :         {
    1197         [ #  # ]:          0 :         if ( endp == orig )
    1198                 :          0 :                 return analyzer->Orig();
    1199                 :            :         else
    1200                 :          0 :                 return analyzer->Resp();
    1201                 :            :         }
    1202                 :            : 
    1203                 :          0 : TCP_RewriterEndpoint* TCP_Rewriter::GetPeer(TCP_RewriterEndpoint* endp)
    1204                 :            :         {
    1205         [ #  # ]:          0 :         if ( endp == orig )
    1206                 :          0 :                 return resp;
    1207                 :            : 
    1208         [ #  # ]:          0 :         else if ( endp == resp )
    1209                 :          0 :                 return orig;
    1210                 :            : 
    1211                 :            :         else
    1212                 :          0 :                 return 0;
    1213                 :            :         }
    1214                 :            : 
    1215                 :            : #define KEEP_ORIG       1
    1216                 :            : #define REUSE_OPT       1
    1217                 :            : #define TO_NOP          0
    1218                 :            : #define MAX_TCP_OPTION_REWRITING        9
    1219                 :            : 
    1220                 :            : struct TCPOptionRewriting {
    1221                 :            :         int keep_orig;
    1222                 :            :         int reuse;
    1223                 :            : } tcp_option_rewriting[MAX_TCP_OPTION_REWRITING] = {
    1224                 :            :         //  0        -    End of Option List                 [RFC793]
    1225                 :            :         {KEEP_ORIG, REUSE_OPT},
    1226                 :            : 
    1227                 :            :         //  1        -    No-Operation                       [RFC793]
    1228                 :            :         {KEEP_ORIG, REUSE_OPT},
    1229                 :            : 
    1230                 :            :         //  2        4    Maximum Segment Size               [RFC793]
    1231                 :            :         {KEEP_ORIG, REUSE_OPT},
    1232                 :            : 
    1233                 :            :         //  3        3    WSOPT - Window Scale              [RFC1323]
    1234                 :            :         {KEEP_ORIG, REUSE_OPT},
    1235                 :            : 
    1236                 :            :         //  4        2    SACK Permitted                    [RFC2018]
    1237                 :            :         {KEEP_ORIG, REUSE_OPT},
    1238                 :            : 
    1239                 :            :         //  5        N    SACK                              [RFC2018]
    1240                 :            :         {TO_NOP, TO_NOP},
    1241                 :            : 
    1242                 :            :         //  6        6    Echo (obsoleted by option 8)      [RFC1072]
    1243                 :            :         {TO_NOP, TO_NOP},
    1244                 :            : 
    1245                 :            :         //  7        6    Echo Reply (obsoleted by option 8)[RFC1072]
    1246                 :            :         {TO_NOP, TO_NOP},
    1247                 :            : 
    1248                 :            :         //  8       10    TSOPT - Time Stamp Option         [RFC1323]
    1249                 :            :         {KEEP_ORIG, REUSE_OPT},
    1250                 :            : 
    1251                 :            :         // ** the rest is left for future work **
    1252                 :            :         //  9        2    Partial Order Connection Permitted[RFC1693]
    1253                 :            :         // 10        3    Partial Order Service Profile     [RFC1693]
    1254                 :            :         // 11             CC                                [RFC1644]
    1255                 :            :         // 12             CC.NEW                            [RFC1644]
    1256                 :            :         // 13             CC.ECHO                           [RFC1644]
    1257                 :            :         // 14         3   TCP Alternate Checksum Request    [RFC1146]
    1258                 :            :         // 15         N   TCP Alternate Checksum Data       [RFC1146]
    1259                 :            :         // 16             Skeeter                           [Knowles]
    1260                 :            :         // 17             Bubba                             [Knowles]
    1261                 :            :         // 18         3   Trailer Checksum Option    [Subbu & Monroe]
    1262                 :            :         // 19        18   MD5 Signature Option              [RFC2385]
    1263                 :            :         // 20             SCPS Capabilities                   [Scott]
    1264                 :            :         // 21           Selective Negative Acknowledgements [Scott]
    1265                 :            :         // 22           Record Boundaries                   [Scott]
    1266                 :            :         // 23           Corruption experienced              [Scott]
    1267                 :            :         // 24           SNAP                             [Sukonnik]
    1268                 :            :         // 25           Unassigned (released 12/18/00)
    1269                 :            :         // 26             TCP Compression Filter           [Bellovin]
    1270                 :            : };
    1271                 :            : 
    1272                 :            : int TCP_Rewriter::RewriteTCPOption(unsigned int opt, unsigned int optlen,
    1273                 :            :                                 const u_char* option, TCP_Analyzer* analyzer,
    1274                 :          0 :                                 bool is_orig, void* cookie)
    1275                 :            :         {
    1276                 :          0 :         TCP_TracePacket* p = (TCP_TracePacket*) cookie;
    1277                 :            : 
    1278 [ #  # ][ #  # ]:          0 :         if ( opt < MAX_TCP_OPTION_REWRITING &&
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
    1279                 :            :              ( (! p->IsReuse() && tcp_option_rewriting[opt].keep_orig) ||
    1280                 :            :                (p->IsReuse() && tcp_option_rewriting[opt].reuse) ) )
    1281                 :            :                 // copy/reuse the TCP option
    1282                 :          0 :                 p->AppendTCPHeader(option, optlen);
    1283                 :            : 
    1284                 :            :         else
    1285                 :            :                 { // replace it with nop
    1286                 :            :                 static const u_char nop[16] = {
    1287                 :            :                         1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1
    1288                 :            :                 };
    1289                 :            : 
    1290         [ #  # ]:          0 :                 while ( optlen > 0 )
    1291                 :            :                         {
    1292                 :          0 :                         int k = optlen > 16 ? 16 : optlen;
    1293                 :          0 :                         p->AppendTCPHeader(nop, k);
    1294                 :          0 :                         optlen -= k;
    1295                 :            :                         }
    1296                 :            :                 }
    1297                 :            : 
    1298                 :          0 :         return 0;
    1299                 :            :         }
    1300                 :            : 
    1301                 :          0 : TCP_RewriteSlot* TCP_Rewriter::add_slot()
    1302                 :            :         {
    1303                 :          0 :         ++highest_slot_number;
    1304                 :            : 
    1305                 :            :         DEBUG_MSG_A("add slot %u\n", highest_slot_number);
    1306                 :            : 
    1307                 :            :         last_slot = current_slot =
    1308                 :          0 :                 new TCP_RewriteSlot(current_packet, highest_slot_number);
    1309                 :            : 
    1310                 :          0 :         slot_queue.push_back(current_slot);
    1311                 :            : 
    1312                 :          0 :         return current_slot;
    1313                 :            :         }
    1314                 :            : 
    1315                 :          0 : TCP_RewriteSlot* TCP_Rewriter::find_slot(unsigned int slot)
    1316                 :            :         {
    1317                 :            :         // DEBUG_MSG_A("%d slots reserved\n", reserved_slots.size());
    1318                 :          0 :         slot_map_t::iterator it = reserved_slots.find(slot);
    1319         [ #  # ]:          0 :         if ( it == reserved_slots.end() )
    1320                 :          0 :                 return 0;
    1321                 :            : 
    1322                 :          0 :         return it->second;
    1323                 :            :         }
    1324                 :            : 
    1325                 :          0 : unsigned int TCP_Rewriter::ReserveSlot()
    1326                 :            :         {
    1327         [ #  # ]:          0 :         if ( ! current_packet )
    1328                 :            :                 {
    1329                 :          0 :                 run_time("cannot reserve a rewrite slot before packet arrival");
    1330                 :          0 :                 return 0;
    1331                 :            :                 }
    1332                 :            : 
    1333         [ #  # ]:          0 :         if ( ! current_slot )
    1334                 :            :                 {
    1335                 :          0 :                 first_slot = add_slot();
    1336                 :          0 :                 HoldPacket(current_packet);
    1337                 :            :                 }
    1338                 :            : 
    1339         [ #  # ]:          0 :         if ( current_slot != last_slot )
    1340                 :            :                 {
    1341                 :          0 :                 run_time("cannot reserve a slot within a reserved slot");
    1342                 :          0 :                 return 0;
    1343                 :            :                 }
    1344                 :            : 
    1345                 :          0 :         int slot_number = current_slot->Number();
    1346                 :            :         DEBUG_MSG_A("reserved slot %d\n", slot_number);
    1347                 :            : 
    1348                 :          0 :         reserved_slots[slot_number] = current_slot;
    1349                 :          0 :         add_slot();
    1350                 :          0 :         current_packet->AddReservedSlot();
    1351                 :            : 
    1352                 :          0 :         return slot_number;
    1353                 :            :         }
    1354                 :            : 
    1355                 :          0 : int TCP_Rewriter::SeekSlot(unsigned int slot)
    1356                 :            :         {
    1357                 :          0 :         TCP_RewriteSlot* s = find_slot(slot);
    1358         [ #  # ]:          0 :         if ( ! s )
    1359                 :          0 :                 return 0;
    1360                 :            : 
    1361                 :          0 :         current_slot = s;
    1362                 :          0 :         return 1;
    1363                 :            :         }
    1364                 :            : 
    1365                 :          0 : int TCP_Rewriter::ReturnFromSlot()
    1366                 :            :         {
    1367                 :          0 :         current_slot = last_slot;
    1368                 :          0 :         return 1;
    1369                 :            :         }
    1370                 :            : 
    1371                 :          0 : int TCP_Rewriter::ReleaseSlot(unsigned int slot)
    1372                 :            :         {
    1373                 :          0 :         slot_map_t::iterator it = reserved_slots.find(slot);
    1374         [ #  # ]:          0 :         if ( it == reserved_slots.end() )
    1375                 :            :                 {
    1376                 :          0 :                 run_time(fmt("cannot find slot %u", slot));
    1377                 :          0 :                 return 0;
    1378                 :            :                 }
    1379                 :            : 
    1380                 :          0 :         TCP_RewriteSlot* s = it->second;
    1381                 :          0 :         reserved_slots.erase(it);
    1382                 :            : 
    1383         [ #  # ]:          0 :         if ( s == current_slot )
    1384                 :          0 :                 ReturnFromSlot();
    1385                 :            : 
    1386                 :            :         DEBUG_MSG_A("release slot %u, slot [%u, %u]\n", s->Number(), first_slot->Number(), last_slot->Number());
    1387         [ #  # ]:          0 :         if ( s == first_slot )
    1388                 :            :                 {
    1389         [ #  # ]:          0 :                 do      // release slots till we get to the next *reserved* slot
    1390                 :            :                         {
    1391                 :            :                         DEBUG_MSG_A("dump slot %d %.6f\n", first_slot->Number(), first_slot->Packet()->TimeStamp());
    1392                 :            : 
    1393                 :          0 :                         first_slot->Dump();
    1394                 :          0 :                         slot_queue.pop_front();
    1395         [ #  # ]:          0 :                         delete first_slot;
    1396                 :            : 
    1397         [ #  # ]:          0 :                         if ( slot_queue.empty() )
    1398                 :            :                                 {
    1399                 :          0 :                                 first_slot = last_slot = current_slot = 0;
    1400                 :            :                                 DEBUG_MSG_A("release all packets on hold\n");
    1401                 :          0 :                                 ReleasePacketsOnHold();
    1402                 :          0 :                                 break;
    1403                 :            :                                 }
    1404                 :            : 
    1405                 :          0 :                         first_slot = slot_queue.front();
    1406                 :          0 :                         HoldPacket(first_slot->Packet());
    1407                 :            :                         DEBUG_MSG_A("move on to packet %d (%.6f)\n", first_slot->Packet()->PacketSeq(), first_slot->Packet()->TimeStamp());
    1408                 :            :                         }
    1409                 :            :                 while ( ! find_slot(first_slot->Number()) );
    1410                 :            :                 }
    1411                 :            : 
    1412                 :          0 :         return 1;
    1413                 :            :         }
    1414                 :            : 
    1415                 :          0 : TCP_RewriteSlot::TCP_RewriteSlot(TCP_TracePacket* p, unsigned int number)
    1416                 :            :         {
    1417                 :          0 :         packet = p;
    1418                 :          0 :         slot_number = number;
    1419                 :          0 :         rewriter = packet->TraceRewriter();
    1420                 :          0 :         }
    1421                 :            : 
    1422                 :          0 : void TCP_RewriteSlot::WriteData(int is_orig, int len, const u_char* data)
    1423                 :            :         {
    1424         [ #  # ]:          0 :         if ( is_orig != packet->IsOrig() )
    1425                 :            :                 {
    1426                 :            :                 run_time("writing data to a slot of wrong direction %s",
    1427                 :          0 :                         rewriter->analyzer->Conn());
    1428                 :            : 
    1429                 :          0 :                 BroString* tmp = new BroString(data, len, 1);
    1430                 :          0 :                 char* tmp_s = tmp->Render();
    1431                 :            :                 run_time(fmt("further info: dir = %s, len = %d, data = \"%s\"",
    1432         [ #  # ]:          0 :                                 is_orig ? "orig" : "resp", len, tmp_s));
    1433                 :          0 :                 delete tmp_s;
    1434         [ #  # ]:          0 :                 delete tmp;
    1435                 :          0 :                 return;
    1436                 :            :                 }
    1437                 :            : 
    1438                 :          0 :         BroString* s = new BroString((const u_char*) data, len, 1);
    1439                 :          0 :         buf.push(s);
    1440                 :            :         }
    1441                 :            : 
    1442                 :          0 : void TCP_RewriteSlot::Dump()
    1443                 :            :         {
    1444         [ #  # ]:          0 :         while ( ! buf.empty() )
    1445                 :            :                 {
    1446                 :          0 :                 BroString* s = buf.front();
    1447                 :          0 :                 buf.pop();
    1448                 :            :                 DEBUG_MSG_A("dump: \"%s\"\n", s->Bytes());
    1449                 :          0 :                 rewriter->DoWriteData(packet->IsOrig(), s->Len(), s->Bytes());
    1450         [ #  # ]:          0 :                 delete s;
    1451                 :            :                 }
    1452                 :          0 :         }
    1453                 :            : 
    1454                 :          6 : static std::queue<TCP_Rewriter*> rewriter_funerals;
    1455                 :          6 : static std::queue<TCP_RewriterEndpoint*> rewriters_to_flush;
    1456                 :            : 
    1457                 :          0 : void schedule_funeral(TCP_Rewriter* rewriter)
    1458                 :            :         {
    1459                 :          0 :         Ref(rewriter->Analyzer()->Conn());
    1460                 :          0 :         rewriter_funerals.push(rewriter);
    1461                 :          0 :         }
    1462                 :            : 
    1463                 :          0 : void schedule_flush(TCP_RewriterEndpoint* endp)
    1464                 :            :         {
    1465                 :          0 :         Ref(endp->Analyzer()->Conn());
    1466                 :          0 :         rewriters_to_flush.push(endp);
    1467                 :          0 :         }
    1468                 :            : 
    1469                 :      42701 : void flush_rewriter_packet()
    1470                 :            :         {
    1471         [ -  + ]:      42701 :         while ( ! rewriter_funerals.empty() )
    1472                 :            :                 {
    1473                 :          0 :                 TCP_Rewriter* rewriter = rewriter_funerals.front();
    1474                 :          0 :                 rewriter_funerals.pop();
    1475                 :          0 :                 rewriter->Funeral();
    1476                 :          0 :                 Unref(rewriter->Analyzer()->Conn());
    1477                 :            :                 }
    1478                 :            : 
    1479         [ -  + ]:      42701 :         while ( ! rewriters_to_flush.empty() )
    1480                 :            :                 {
    1481                 :          0 :                 TCP_RewriterEndpoint* endp = rewriters_to_flush.front();
    1482                 :          0 :                 rewriters_to_flush.pop();
    1483                 :            : 
    1484         [ #  # ]:          0 :                 if ( endp )
    1485                 :            :                         {
    1486                 :          0 :                         endp->Flush();
    1487                 :          0 :                         Unref(endp->Analyzer()->Conn());
    1488                 :            :                         }
    1489                 :            :                 }
    1490                 :            : 
    1491         [ -  + ]:      42701 :         if ( mgr.HasEvents() )
    1492                 :          0 :                 internal_error("flushing packets generates additional events!");
    1493                 :      42701 :         }
    1494                 :            : 
    1495                 :          0 : TCP_SourcePacket::TCP_SourcePacket(const struct pcap_pkthdr* pcap_hdr, const u_char* pcap_pkt)
    1496                 :            :         {
    1497                 :          0 :         hdr = *pcap_hdr;
    1498 [ #  # ][ #  # ]:          0 :         if ( pcap_pkt )
    1499                 :            :                 {
    1500                 :          0 :                 pkt = new u_char[hdr.caplen];
    1501                 :          0 :                 memcpy(pkt, pcap_pkt, hdr.caplen);
    1502                 :            :                 }
    1503                 :            :         else
    1504                 :            :                 {
    1505                 :          0 :                 hdr.caplen = 0;
    1506                 :          0 :                 pkt = 0;
    1507                 :            :                 }
    1508                 :          0 :         }
    1509                 :            : 
    1510                 :          0 : TCP_SourcePacket::~TCP_SourcePacket()
    1511                 :            :         {
    1512 [ #  # ][ #  # ]:          0 :         delete [] pkt;
    1513                 :          0 :         }
    1514                 :            : 
    1515                 :          0 : TCP_SourcePacketWriter::TCP_SourcePacketWriter(TCP_Analyzer* analyzer, PacketDumper* arg_dumper)
    1516                 :            :         {
    1517                 :          0 :         dumper = arg_dumper;
    1518                 :          0 :         }
    1519                 :            : 
    1520                 :          0 : TCP_SourcePacketWriter::~TCP_SourcePacketWriter()
    1521                 :            :         {
    1522                 :            :         // By default discard all packets of the connection
    1523                 :            :         // if they are not explicitly dumped.
    1524                 :          0 :         Purge(false);
    1525                 :          0 :         }
    1526                 :            : 
    1527                 :            : void TCP_SourcePacketWriter::NextPacket(const struct pcap_pkthdr* pcap_hdr,
    1528                 :          0 :                                         const u_char* pcap_pkt)
    1529                 :            :         {
    1530                 :          0 :         source_packets.push(new TCP_SourcePacket(pcap_hdr, pcap_pkt));
    1531                 :          0 :         }
    1532                 :            : 
    1533                 :          0 : void TCP_SourcePacketWriter::Purge(bool dump)
    1534                 :            :         {
    1535         [ #  # ]:          0 :         while ( ! source_packets.empty() )
    1536                 :            :                 {
    1537                 :          0 :                 TCP_SourcePacket* p = source_packets.front();
    1538         [ #  # ]:          0 :                 if ( dump )
    1539                 :          0 :                         dumper->DumpPacket(p->Hdr(), p->Pkt(), p->Len());
    1540                 :          0 :                 source_packets.pop();
    1541         [ #  # ]:          0 :                 delete p;
    1542                 :            :                 }
    1543                 :          0 :         }
    1544                 :            : 
    1545                 :          0 : void TCP_SourcePacketWriter::Dump()
    1546                 :            :         {
    1547                 :          0 :         Purge(true);
    1548                 :          0 :         }
    1549                 :            : 
    1550                 :          0 : void TCP_SourcePacketWriter::Abort()
    1551                 :            :         {
    1552                 :          0 :         Purge(false);
    1553                 :          0 :         }
    1554                 :            : 
    1555                 :          0 : TCP_SourcePacketWriter* get_src_pkt_writer(TCP_Analyzer* analyzer)
    1556                 :            :         {
    1557 [ #  # ][ #  # ]:          0 :         if ( ! analyzer || analyzer->Conn()->ConnTransport() != TRANSPORT_TCP )
                 [ #  # ]
    1558                 :          0 :                 internal_error("connection for the trace rewriter does not exist");
    1559                 :            : 
    1560                 :          0 :         TCP_SourcePacketWriter* writer = analyzer->SourcePacketWriter();
    1561         [ #  # ]:          0 :         if ( ! writer )
    1562                 :            :                 {
    1563         [ #  # ]:          0 :                 if ( ! pkt_dumper )
    1564                 :          0 :                         return 0;       // don't complain if no output file
    1565         [ #  # ]:          0 :                 else if ( ! dump_selected_source_packets )
    1566                 :          0 :                         builtin_run_time("flag dump_source_packets is not set");
    1567                 :            :                 else
    1568                 :          0 :                         internal_error("source packet writer not initialized");
    1569                 :            :                 }
    1570                 :            : 
    1571                 :          0 :         return writer;
    1572                 :            :         }
    1573                 :            : 
    1574                 :            : 
    1575                 :            : #include "common-rw.bif.func_def"

Generated by: LCOV version 1.8