LCOV - code coverage report
Current view: top level - src - PIA.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 102 184 55.4 %
Date: 2010-12-13 Functions: 16 27 59.3 %
Branches: 42 102 41.2 %

           Branch data     Line data    Source code
       1                 :            : // $Id: PIA.cc,v 1.1.2.14 2006/05/31 23:19:07 sommer Exp $
       2                 :            : 
       3                 :            : #include "PIA.h"
       4                 :            : #include "RuleMatcher.h"
       5                 :            : #include "TCP_Reassembler.h"
       6                 :            : 
       7                 :       1622 : PIA::PIA(Analyzer* arg_as_analyzer)
       8                 :            :         {
       9                 :       1622 :         current_packet.data = 0;
      10                 :       1622 :         as_analyzer = arg_as_analyzer;
      11                 :       1622 :         }
      12                 :            : 
      13                 :       1622 : PIA::~PIA()
      14                 :            :         {
      15                 :       1622 :         ClearBuffer(&pkt_buffer);
      16 [ #  # ][ #  # ]:       1622 :         }
                 [ -  + ]
      17                 :            : 
      18                 :       2560 : void PIA::ClearBuffer(Buffer* buffer)
      19                 :            :         {
      20                 :       2560 :         DataBlock* next = 0;
      21         [ +  + ]:       5615 :         for ( DataBlock* b = buffer->head; b; b = next )
      22                 :            :                 {
      23                 :       3055 :                 next = b->next;
      24         [ +  + ]:       3055 :                 delete [] b->data;
      25                 :       3055 :                 delete b;
      26                 :            :                 }
      27                 :            : 
      28                 :       2560 :         buffer->head = buffer->tail = 0;
      29                 :       2560 :         buffer->size = 0;
      30                 :       2560 :         }
      31                 :            : 
      32                 :            : void PIA::AddToBuffer(Buffer* buffer, int seq, int len, const u_char* data,
      33                 :       3055 :                         bool is_orig)
      34                 :            :         {
      35                 :       3055 :         u_char* tmp = 0;
      36                 :            : 
      37         [ +  + ]:       3055 :         if ( data )
      38                 :            :                 {
      39                 :       2986 :                 tmp = new u_char[len];
      40                 :       2986 :                 memcpy(tmp, data, len);
      41                 :            :                 }
      42                 :            : 
      43                 :       3055 :         DataBlock* b = new DataBlock;
      44                 :       3055 :         b->data = tmp;
      45                 :       3055 :         b->is_orig = is_orig;
      46                 :       3055 :         b->len = len;
      47                 :       3055 :         b->seq = seq;
      48                 :       3055 :         b->next = 0;
      49                 :            : 
      50         [ +  + ]:       3055 :         if ( buffer->tail )
      51                 :            :                 {
      52                 :       1648 :                 buffer->tail->next = b;
      53                 :       1648 :                 buffer->tail = b;
      54                 :            :                 }
      55                 :            :         else
      56                 :       1407 :                 buffer->head = buffer->tail = b;
      57                 :            : 
      58                 :       3055 :         buffer->size += len;
      59                 :       3055 :         }
      60                 :            : 
      61                 :       1478 : void PIA::AddToBuffer(Buffer* buffer, int len, const u_char* data, bool is_orig)
      62                 :            :         {
      63                 :       1478 :         AddToBuffer(buffer, -1, len, data, is_orig);
      64                 :       1478 :         }
      65                 :            : 
      66                 :          0 : void PIA::ReplayPacketBuffer(Analyzer* analyzer)
      67                 :            :         {
      68                 :          0 :         DBG_LOG(DBG_DPD, "PIA replaying %d total packet bytes", pkt_buffer.size);
      69                 :            : 
      70         [ #  # ]:          0 :         for ( DataBlock* b = pkt_buffer.head; b; b = b->next )
      71                 :          0 :                 analyzer->DeliverPacket(b->len, b->data, b->is_orig, -1, 0, 0);
      72                 :          0 :         }
      73                 :            : 
      74                 :       1622 : void PIA::PIA_Done()
      75                 :            :         {
      76                 :       1622 :         FinishEndpointMatcher();
      77                 :       1622 :         }
      78                 :            : 
      79                 :            : void PIA::PIA_DeliverPacket(int len, const u_char* data, bool is_orig, int seq,
      80                 :       1683 :                                 const IP_Hdr* ip, int caplen)
      81                 :            :         {
      82         [ +  + ]:       1683 :         if ( pkt_buffer.state == SKIPPING )
      83                 :        175 :                 return;
      84                 :            : 
      85                 :       1508 :         current_packet.data = data;
      86                 :       1508 :         current_packet.len = len;
      87                 :       1508 :         current_packet.seq = seq;
      88                 :       1508 :         current_packet.is_orig = is_orig;
      89                 :            : 
      90                 :       1508 :         State new_state = pkt_buffer.state;
      91                 :            : 
      92         [ +  + ]:       1508 :         if ( pkt_buffer.state == INIT )
      93                 :        684 :                 new_state = BUFFERING;
      94                 :            : 
      95 [ +  + ][ +  - ]:       1508 :         if ( (pkt_buffer.state == BUFFERING || new_state == BUFFERING) &&
                 [ +  - ]
      96                 :            :              len > 0 )
      97                 :            :                 {
      98                 :       1508 :                 AddToBuffer(&pkt_buffer, seq, len, data, is_orig);
      99         [ +  + ]:       1508 :                 if ( pkt_buffer.size > dpd_buffer_size )
     100                 :            :                         new_state = dpd_match_only_beginning ?
     101         [ +  - ]:         26 :                                                 SKIPPING : MATCHING_ONLY;
     102                 :            :                 }
     103                 :            : 
     104                 :            :         // FIXME: I'm not sure why it does not work with eol=true...
     105                 :       1508 :         DoMatch(data, len, is_orig, true, false, false, ip);
     106                 :            : 
     107                 :       1508 :         pkt_buffer.state = new_state;
     108                 :            : 
     109                 :       1683 :         current_packet.data = 0;
     110                 :            :         }
     111                 :            : 
     112                 :            : void PIA::Match(Rule::PatternType type, const u_char* data, int len,
     113                 :      26764 :                 bool is_orig, bool bol, bool eol, bool clear_state)
     114                 :            :         {
     115         [ +  - ]:      26764 :         if ( ! MatcherInitialized(is_orig) )
     116                 :      26764 :                 InitEndpointMatcher(AsAnalyzer(), 0, 0, is_orig, this);
     117                 :            : 
     118                 :      26764 :         RuleMatcherState::Match(type, data, len, is_orig, bol, eol, clear_state);
     119                 :      26764 :         }
     120                 :            : 
     121                 :            : void PIA::DoMatch(const u_char* data, int len, bool is_orig, bool bol, bool eol,
     122                 :       4708 :                         bool clear_state, const IP_Hdr* ip)
     123                 :            :         {
     124         [ +  - ]:       4708 :         if ( ! rule_matcher )
     125                 :       4708 :                 return;
     126                 :            : 
     127         [ #  # ]:          0 :         if ( ! MatcherInitialized(is_orig) )
     128                 :          0 :                 InitEndpointMatcher(AsAnalyzer(), ip, len, is_orig, this);
     129                 :            : 
     130                 :            :         RuleMatcherState::Match(Rule::PAYLOAD, data, len, is_orig,
     131                 :       4708 :                                 bol, eol, clear_state);
     132                 :            :         }
     133                 :            : 
     134                 :          0 : void PIA_UDP::ActivateAnalyzer(AnalyzerTag::Tag tag, const Rule* rule)
     135                 :            :         {
     136         [ #  # ]:          0 :         if ( pkt_buffer.state == MATCHING_ONLY )
     137                 :            :                 {
     138                 :          0 :                 DBG_LOG(DBG_DPD, "analyzer found but buffer already exceeded");
     139                 :            :                 // FIXME: This is where to check whether an analyzer
     140                 :            :                 // supports partial connections once we get such.
     141                 :          0 :                 return;
     142                 :            :                 }
     143                 :            : 
     144         [ #  # ]:          0 :         if ( Parent()->HasChildAnalyzer(tag) )
     145                 :          0 :                 return;
     146                 :            : 
     147                 :          0 :         Analyzer* a = Parent()->AddChildAnalyzer(tag);
     148                 :          0 :         a->SetSignature(rule);
     149                 :            : 
     150         [ #  # ]:          0 :         if ( a )
     151                 :          0 :                 ReplayPacketBuffer(a);
     152                 :            :         }
     153                 :            : 
     154                 :          0 : void PIA_UDP::DeactivateAnalyzer(AnalyzerTag::Tag tag)
     155                 :            :         {
     156                 :          0 :         internal_error("PIA_UDP::Deact not implemented yet");
     157                 :            :         }
     158                 :            : 
     159                 :            : //// TCP PIA
     160                 :            : 
     161                 :        938 : PIA_TCP::~PIA_TCP()
     162                 :            :         {
     163                 :        938 :         ClearBuffer(&stream_buffer);
     164 [ +  - ][ #  # ]:        938 :         }
                 [ #  # ]
     165                 :            : 
     166                 :        938 : void PIA_TCP::Init()
     167                 :            :         {
     168                 :        938 :         TCP_ApplicationAnalyzer::Init();
     169                 :            : 
     170         [ +  - ]:        938 :         if ( Parent()->GetTag() == AnalyzerTag::TCP )
     171                 :            :                 {
     172                 :        938 :                 TCP_Analyzer* tcp = static_cast<TCP_Analyzer*>(Parent());
     173                 :        938 :                 SetTCP(tcp);
     174                 :        938 :                 tcp->SetPIA(this);
     175                 :            :                 }
     176                 :        938 :         }
     177                 :            : 
     178                 :       1722 : void PIA_TCP::FirstPacket(bool is_orig, const IP_Hdr* ip)
     179                 :            :         {
     180                 :            :         static char dummy_packet[sizeof(struct ip) + sizeof(struct tcphdr)];
     181                 :            :         static struct ip* ip4 = 0;
     182                 :            :         static struct tcphdr* tcp4 = 0;
     183                 :            :         static IP_Hdr* ip4_hdr = 0;
     184                 :            : 
     185         [ +  + ]:       1722 :         DBG_LOG(DBG_DPD, "PIA_TCP[%d] FirstPacket(%s)", GetID(), (is_orig ? "T" : "F"));
     186                 :            : 
     187         [ -  + ]:       1722 :         if ( ! ip )
     188                 :            :                 {
     189                 :            :                 // Create a dummy packet.  Not very elegant, but everything
     190                 :            :                 // else would be *really* ugly ...
     191         [ #  # ]:          0 :                 if ( ! ip4_hdr )
     192                 :            :                         {
     193                 :          0 :                         ip4 = (struct ip*) dummy_packet;
     194                 :            :                         tcp4 = (struct tcphdr*)
     195                 :          0 :                                 (dummy_packet + sizeof(struct ip));
     196                 :          0 :                         ip4->ip_len = sizeof(struct ip) + sizeof(struct tcphdr);
     197                 :          0 :                         ip4->ip_hl = sizeof(struct ip) >> 2;
     198                 :          0 :                         ip4->ip_p = IPPROTO_TCP;
     199                 :            : 
     200                 :            :                         // Cast to const so that it doesn't delete it.
     201                 :          0 :                         ip4_hdr = new IP_Hdr((const struct ip*) ip4);
     202                 :            :                         }
     203                 :            : 
     204         [ #  # ]:          0 :                 if ( is_orig )
     205                 :            :                         {
     206                 :          0 :                         copy_addr(Conn()->OrigAddr(), &ip4->ip_src.s_addr);
     207                 :          0 :                         copy_addr(Conn()->RespAddr(), &ip4->ip_dst.s_addr);
     208                 :          0 :                         tcp4->th_sport = htons(Conn()->OrigPort());
     209                 :          0 :                         tcp4->th_dport = htons(Conn()->RespPort());
     210                 :            :                         }
     211                 :            :                 else
     212                 :            :                         {
     213                 :          0 :                         copy_addr(Conn()->RespAddr(), &ip4->ip_src.s_addr);
     214                 :          0 :                         copy_addr(Conn()->OrigAddr(), &ip4->ip_dst.s_addr);
     215                 :          0 :                         tcp4->th_sport = htons(Conn()->RespPort());
     216                 :          0 :                         tcp4->th_dport = htons(Conn()->OrigPort());
     217                 :            :                         }
     218                 :            : 
     219                 :          0 :                 ip = ip4_hdr;
     220                 :            :                 }
     221                 :            : 
     222         [ +  - ]:       1722 :         if ( ! MatcherInitialized(is_orig) )
     223                 :       1722 :                 DoMatch((const u_char*)"", 0, is_orig, true, false, false, ip);
     224                 :       1722 :         }
     225                 :            : 
     226                 :       7962 : void PIA_TCP::DeliverStream(int len, const u_char* data, bool is_orig)
     227                 :            :         {
     228                 :       7962 :         TCP_ApplicationAnalyzer::DeliverStream(len, data, is_orig);
     229                 :            : 
     230         [ +  + ]:       7962 :         if ( stream_buffer.state == SKIPPING )
     231                 :       6484 :                 return;
     232                 :            : 
     233                 :       1478 :         stream_mode = true;
     234                 :            : 
     235                 :       1478 :         State new_state = stream_buffer.state;
     236                 :            : 
     237         [ +  + ]:       1478 :         if ( stream_buffer.state == INIT )
     238                 :            :                 {
     239                 :            :                 // FIXME: clear payload-matching state here...
     240                 :        723 :                 new_state = BUFFERING;
     241                 :            :                 }
     242                 :            : 
     243 [ +  + ][ +  - ]:       1478 :         if ( stream_buffer.state == BUFFERING || new_state == BUFFERING )
     244                 :            :                 {
     245                 :       1478 :                 AddToBuffer(&stream_buffer, len, data, is_orig);
     246         [ +  + ]:       1478 :                 if ( stream_buffer.size > dpd_buffer_size )
     247                 :            :                         new_state = dpd_match_only_beginning ?
     248         [ +  - ]:        603 :                                                 SKIPPING : MATCHING_ONLY;
     249                 :            :                 }
     250                 :            : 
     251                 :       1478 :         DoMatch(data, len, is_orig, false, false, false, 0);
     252                 :            : 
     253                 :       7962 :         stream_buffer.state = new_state;
     254                 :            :         }
     255                 :            : 
     256                 :        567 : void PIA_TCP::Undelivered(int seq, int len, bool is_orig)
     257                 :            :         {
     258                 :        567 :         TCP_ApplicationAnalyzer::Undelivered(seq, len, is_orig);
     259                 :            : 
     260         [ +  + ]:        567 :         if ( stream_buffer.state == BUFFERING )
     261                 :            :                 // We use data=nil to mark an undelivered.
     262                 :         69 :                 AddToBuffer(&stream_buffer, seq, len, 0, is_orig);
     263                 :            : 
     264                 :            :         // No check for buffer overrun here. I think that's ok.
     265                 :        567 :         }
     266                 :            : 
     267                 :          0 : void PIA_TCP::ActivateAnalyzer(AnalyzerTag::Tag tag, const Rule* rule)
     268                 :            :         {
     269         [ #  # ]:          0 :         if ( stream_buffer.state == MATCHING_ONLY )
     270                 :            :                 {
     271                 :          0 :                 DBG_LOG(DBG_DPD, "analyzer found but buffer already exceeded");
     272                 :            :                 // FIXME: This is where to check whether an analyzer supports
     273                 :            :                 // partial connections once we get such.
     274                 :          0 :                 return;
     275                 :            :                 }
     276                 :            : 
     277         [ #  # ]:          0 :         if ( Parent()->HasChildAnalyzer(tag) )
     278                 :          0 :                 return;
     279                 :            : 
     280                 :          0 :         Analyzer* a = Parent()->AddChildAnalyzer(tag);
     281                 :          0 :         a->SetSignature(rule);
     282                 :            : 
     283                 :            :         // We have two cases here:
     284                 :            :         //
     285                 :            :         // (a) We have already got stream input.
     286                 :            :         //     => Great, somebody's already reassembling and we can just
     287                 :            :         //              replay our stream buffer to the new analyzer.
     288         [ #  # ]:          0 :         if ( stream_mode )
     289                 :            :                 {
     290                 :          0 :                 ReplayStreamBuffer(a);
     291                 :          0 :                 return;
     292                 :            :                 }
     293                 :            : 
     294                 :            :         // (b) We have only got packet input so far (or none at all).
     295                 :            :         //     => We have to switch from packet-mode to stream-mode.
     296                 :            :         //
     297                 :            :         // Here's what we do:
     298                 :            :         //
     299                 :            :         //   (1) We create new TCP_Reassemblers and feed them the buffered
     300                 :            :         //       packets.
     301                 :            :         //
     302                 :            :         //   (2) The reassembler will give us their results via the
     303                 :            :         //       stream-interface and we buffer it as usual.
     304                 :            :         //
     305                 :            :         //   (3) We replay the now-filled stream-buffer to the analyzer.
     306                 :            :         //
     307                 :            :         //   (4) We hand the two reassemblers to the TCP Analyzer (our parent),
     308                 :            :         //       turning reassembly now on for all subsequent data.
     309                 :            : 
     310                 :          0 :         DBG_LOG(DBG_DPD, "DPM_TCP switching from packet-mode to stream-mode");
     311                 :          0 :         stream_mode = true;
     312                 :            : 
     313                 :            :         // FIXME: The reassembler will query the endpoint for state. Not sure
     314                 :            :         // if this is works in all cases...
     315                 :            : 
     316         [ #  # ]:          0 :         if ( Parent()->GetTag() != AnalyzerTag::TCP )
     317                 :            :                 {
     318                 :            :                 // Our parent is not the TCP analyzer, which can only mean
     319                 :            :                 // we have been inserted somewhere further down in the
     320                 :            :                 // analyzer tree.  In this case, we will never have seen
     321                 :            :                 // any input at this point (because we don't get packets).
     322         [ #  # ]:          0 :                 assert(!pkt_buffer.head);
     323         [ #  # ]:          0 :                 assert(!stream_buffer.head);
     324                 :          0 :                 return;
     325                 :            :                 }
     326                 :            : 
     327                 :          0 :         TCP_Analyzer* tcp = (TCP_Analyzer*) Parent();
     328                 :            : 
     329                 :            :         TCP_Reassembler* reass_orig =
     330                 :            :                 new TCP_Reassembler(this, tcp, TCP_Reassembler::Direct,
     331                 :          0 :                                         true, tcp->Orig());
     332                 :            : 
     333                 :            :         TCP_Reassembler* reass_resp =
     334                 :            :                 new TCP_Reassembler(this, tcp, TCP_Reassembler::Direct,
     335                 :          0 :                                         false, tcp->Resp());
     336                 :            : 
     337                 :          0 :         int orig_seq = 0;
     338                 :          0 :         int resp_seq = 0;
     339                 :            : 
     340         [ #  # ]:          0 :         for ( DataBlock* b = pkt_buffer.head; b; b = b->next )
     341                 :            :                 {
     342         [ #  # ]:          0 :                 if ( b->is_orig )
     343                 :            :                         reass_orig->DataSent(network_time, orig_seq = b->seq,
     344                 :          0 :                                                 b->len, b->data, true);
     345                 :            :                 else
     346                 :            :                         reass_resp->DataSent(network_time, resp_seq = b->seq,
     347                 :          0 :                                                 b->len, b->data, true);
     348                 :            :                 }
     349                 :            : 
     350                 :            :         // We also need to pass the current packet on.
     351                 :          0 :         DataBlock* current = CurrentPacket();
     352         [ #  # ]:          0 :         if ( current->data )
     353                 :            :                 {
     354         [ #  # ]:          0 :                 if ( current->is_orig )
     355                 :            :                         reass_orig->DataSent(network_time,
     356                 :            :                                         orig_seq = current->seq,
     357                 :          0 :                                         current->len, current->data, true);
     358                 :            :                 else
     359                 :            :                         reass_resp->DataSent(network_time,
     360                 :            :                                         resp_seq = current->seq,
     361                 :          0 :                                         current->len, current->data, true);
     362                 :            :                 }
     363                 :            : 
     364                 :          0 :         ClearBuffer(&pkt_buffer);
     365                 :            : 
     366                 :          0 :         ReplayStreamBuffer(a);
     367                 :          0 :         reass_orig->AckReceived(orig_seq);
     368                 :          0 :         reass_resp->AckReceived(resp_seq);
     369                 :            : 
     370                 :          0 :         reass_orig->SetType(TCP_Reassembler::Forward);
     371                 :          0 :         reass_resp->SetType(TCP_Reassembler::Forward);
     372                 :            : 
     373                 :          0 :         tcp->SetReassembler(reass_orig, reass_resp);
     374                 :            :         }
     375                 :            : 
     376                 :          0 : void PIA_TCP::DeactivateAnalyzer(AnalyzerTag::Tag tag)
     377                 :            :         {
     378                 :          0 :         internal_error("PIA_TCP::Deact not implemented yet");
     379                 :            :         }
     380                 :            : 
     381                 :          0 : void PIA_TCP::ReplayStreamBuffer(Analyzer* analyzer)
     382                 :            :         {
     383                 :          0 :         DBG_LOG(DBG_DPD, "PIA_TCP replaying %d total stream bytes", stream_buffer.size);
     384                 :            : 
     385         [ #  # ]:          0 :         for ( DataBlock* b = stream_buffer.head; b; b = b->next )
     386                 :            :                 {
     387         [ #  # ]:          0 :                 if ( b->data )
     388                 :          0 :                         analyzer->NextStream(b->len, b->data, b->is_orig);
     389                 :            :                 else
     390                 :          0 :                         analyzer->NextUndelivered(b->seq, b->len, b->is_orig);
     391                 :            :                 }
     392 [ +  - ][ +  - ]:          6 :         }

Generated by: LCOV version 1.8