LCOV - code coverage report
Current view: top level - src - RPC.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 2 286 0.7 %
Date: 2010-12-13 Functions: 2 42 4.8 %
Branches: 2 218 0.9 %

           Branch data     Line data    Source code
       1                 :            : // $Id: RPC.cc 6219 2008-10-01 05:39:07Z vern $
       2                 :            : //
       3                 :            : // See the file "COPYING" in the main distribution directory for copyright.
       4                 :            : 
       5                 :            : #include "config.h"
       6                 :            : 
       7                 :            : #include <stdlib.h>
       8                 :            : 
       9                 :            : #include "NetVar.h"
      10                 :            : #include "XDR.h"
      11                 :            : #include "RPC.h"
      12                 :            : #include "Sessions.h"
      13                 :            : 
      14                 :            : namespace { // local namespace
      15                 :            :         const bool DEBUG_rpc_resync = false;
      16                 :            : }
      17                 :            : 
      18                 :            : #define MAX_RPC_LEN 65536
      19                 :            : 
      20                 :            : // The following correspond to the different RPC status values defined
      21                 :            : // in bro.init.
      22                 :            : // #define BRO_RPC_TIMEOUT 6
      23                 :            : // #define BRO_RPC_AUTH_ERROR 7
      24                 :            : // #define BRO_RPC_UNKNOWN_ERROR 8
      25                 :            : 
      26                 :          0 : RPC_CallInfo::RPC_CallInfo(uint32 arg_xid, const u_char*& buf, int& n)
      27                 :            :         {
      28                 :          0 :         xid = arg_xid;
      29                 :            : 
      30                 :          0 :         start_time = network_time;
      31                 :          0 :         call_n = n;
      32                 :          0 :         call_buf = new u_char[call_n];
      33                 :          0 :         memcpy((void*) call_buf, (const void*) buf, call_n);
      34                 :            : 
      35                 :          0 :         rpc_version = extract_XDR_uint32(buf, n);
      36                 :          0 :         prog = extract_XDR_uint32(buf, n);
      37                 :          0 :         vers = extract_XDR_uint32(buf, n);
      38                 :          0 :         proc = extract_XDR_uint32(buf, n);
      39                 :          0 :         cred_flavor = skip_XDR_opaque_auth(buf, n);
      40                 :          0 :         verf_flavor = skip_XDR_opaque_auth(buf, n);
      41                 :            : 
      42                 :          0 :         header_len = call_n - n;
      43                 :            : 
      44                 :          0 :         valid_call = false;
      45                 :            : 
      46                 :          0 :         v = 0;
      47                 :          0 :         }
      48                 :            : 
      49                 :          0 : RPC_CallInfo::~RPC_CallInfo()
      50                 :            :         {
      51 [ #  # ][ #  # ]:          0 :         delete [] call_buf;
      52                 :          0 :         Unref(v);
      53                 :          0 :         }
      54                 :            : 
      55                 :          0 : int RPC_CallInfo::CompareRexmit(const u_char* buf, int n) const
      56                 :            :         {
      57         [ #  # ]:          0 :         if ( n != call_n )
      58                 :          0 :                 return 0;
      59                 :            : 
      60                 :          0 :         return memcmp((const void*) call_buf, (const void*) buf, call_n) == 0;
      61                 :            :         }
      62                 :            : 
      63                 :            : 
      64                 :          0 : void rpc_callinfo_delete_func(void* v)
      65                 :            :         {
      66         [ #  # ]:          0 :         delete (RPC_CallInfo*) v;
      67                 :          0 :         }
      68                 :            : 
      69                 :          0 : RPC_Interpreter::RPC_Interpreter(Analyzer* arg_analyzer)
      70                 :            :         {
      71                 :          0 :         analyzer = arg_analyzer;
      72                 :          0 :         calls.SetDeleteFunc(rpc_callinfo_delete_func);
      73                 :          0 :         }
      74                 :            : 
      75                 :          0 : RPC_Interpreter::~RPC_Interpreter()
      76                 :            :         {
      77 [ #  # ][ #  # ]:          0 :         }
                 [ #  # ]
      78                 :            : 
      79                 :          0 : int RPC_Interpreter::DeliverRPC(const u_char* buf, int n, int is_orig)
      80                 :            :         {
      81                 :          0 :         uint32 xid = extract_XDR_uint32(buf, n);
      82                 :          0 :         uint32 msg_type = extract_XDR_uint32(buf, n);
      83                 :            : 
      84         [ #  # ]:          0 :         if ( ! buf )
      85                 :          0 :                 return 0;
      86                 :            : 
      87                 :          0 :         HashKey h(&xid, 1);
      88                 :          0 :         RPC_CallInfo* call = calls.Lookup(&h);
      89                 :            : 
      90         [ #  # ]:          0 :         if ( msg_type == RPC_CALL )
      91                 :            :                 {
      92         [ #  # ]:          0 :                 if ( ! is_orig )
      93                 :          0 :                         Weird("responder_RPC_call");
      94                 :            : 
      95         [ #  # ]:          0 :                 if ( call )
      96                 :            :                         {
      97         [ #  # ]:          0 :                         if ( ! call->CompareRexmit(buf, n) )
      98                 :          0 :                                 Weird("RPC_rexmit_inconsistency");
      99                 :            : 
     100         [ #  # ]:          0 :                         if ( call->HeaderLen() > n )
     101                 :            :                                 {
     102                 :          0 :                                 Weird("RPC_underflow");
     103                 :          0 :                                 return 0;
     104                 :            :                                 }
     105                 :            : 
     106                 :          0 :                         n -= call->HeaderLen();
     107                 :          0 :                         buf += call->HeaderLen();
     108                 :            :                         }
     109                 :            : 
     110                 :            :                 else
     111                 :            :                         {
     112                 :          0 :                         call = new RPC_CallInfo(xid, buf, n);
     113         [ #  # ]:          0 :                         if ( ! buf )
     114                 :            :                                 {
     115         [ #  # ]:          0 :                                 delete call;
     116                 :          0 :                                 return 0;
     117                 :            :                                 }
     118                 :            : 
     119                 :          0 :                         calls.Insert(&h, call);
     120                 :            :                         }
     121                 :            : 
     122         [ #  # ]:          0 :                 if ( RPC_BuildCall(call, buf, n) )
     123                 :          0 :                         call->SetValidCall();
     124                 :            :                 else
     125                 :            :                         {
     126                 :          0 :                         Weird("bad_RPC");
     127                 :          0 :                         return 0;
     128                 :            :                         }
     129                 :            :                 }
     130                 :            : 
     131         [ #  # ]:          0 :         else if ( msg_type == RPC_REPLY )
     132                 :            :                 {
     133         [ #  # ]:          0 :                 if ( is_orig )
     134                 :          0 :                         Weird("originator_RPC_reply");
     135                 :            : 
     136                 :          0 :                 uint32 reply_stat = extract_XDR_uint32(buf, n);
     137         [ #  # ]:          0 :                 if ( ! buf )
     138                 :          0 :                         return 0;
     139                 :            : 
     140                 :          0 :                 uint32 status = BroEnum::RPC_UNKNOWN_ERROR;
     141                 :            : 
     142         [ #  # ]:          0 :                 if ( reply_stat == RPC_MSG_ACCEPTED )
     143                 :            :                         {
     144                 :          0 :                         (void) skip_XDR_opaque_auth(buf, n);
     145                 :          0 :                         uint32 accept_stat = extract_XDR_uint32(buf, n);
     146                 :            : 
     147                 :            :                         // The first members of BroEnum::RPC_* correspond
     148                 :            :                         // to accept_stat.
     149         [ #  # ]:          0 :                         if ( accept_stat <= RPC_SYSTEM_ERR )
     150                 :          0 :                                 status = accept_stat;
     151                 :            : 
     152         [ #  # ]:          0 :                         if ( ! buf )
     153                 :          0 :                                 return 0;
     154                 :            : 
     155         [ #  # ]:          0 :                         if ( accept_stat == RPC_PROG_MISMATCH )
     156                 :            :                                 {
     157                 :          0 :                                 (void) extract_XDR_uint32(buf, n);
     158                 :          0 :                                 (void) extract_XDR_uint32(buf, n);
     159                 :            : 
     160         [ #  # ]:          0 :                                 if ( ! buf )
     161                 :          0 :                                         return 0;
     162                 :            :                                 }
     163                 :            :                         }
     164                 :            : 
     165         [ #  # ]:          0 :                 else if ( reply_stat == RPC_MSG_DENIED )
     166                 :            :                         {
     167                 :          0 :                         uint32 reject_stat = extract_XDR_uint32(buf, n);
     168         [ #  # ]:          0 :                         if ( ! buf )
     169                 :          0 :                                 return 0;
     170                 :            : 
     171         [ #  # ]:          0 :                         if ( reject_stat == RPC_MISMATCH )
     172                 :            :                                 {
     173                 :            :                                 // Note that RPC_MISMATCH == 0 == RPC_SUCCESS.
     174                 :          0 :                                 status = BroEnum::RPC_VERS_MISMATCH;
     175                 :            : 
     176                 :          0 :                                 (void) extract_XDR_uint32(buf, n);
     177                 :          0 :                                 (void) extract_XDR_uint32(buf, n);
     178                 :            : 
     179         [ #  # ]:          0 :                                 if ( ! buf )
     180                 :          0 :                                         return 0;
     181                 :            :                                 }
     182                 :            : 
     183         [ #  # ]:          0 :                         else if ( reject_stat == RPC_AUTH_ERROR )
     184                 :            :                                 {
     185                 :          0 :                                 status = BroEnum::RPC_AUTH_ERROR;
     186                 :            : 
     187                 :          0 :                                 (void) extract_XDR_uint32(buf, n);
     188         [ #  # ]:          0 :                                 if ( ! buf )
     189                 :          0 :                                         return 0;
     190                 :            :                                 }
     191                 :            : 
     192                 :            :                         else
     193                 :            :                                 {
     194                 :          0 :                                 status = BroEnum::RPC_UNKNOWN_ERROR;
     195                 :          0 :                                 Weird("bad_RPC");
     196                 :            :                                 }
     197                 :            :                         }
     198                 :            : 
     199                 :            :                 else
     200                 :          0 :                         Weird("bad_RPC");
     201                 :            : 
     202         [ #  # ]:          0 :                 if ( call )
     203                 :            :                         {
     204                 :          0 :                         int success = status == RPC_SUCCESS;
     205                 :            : 
     206         [ #  # ]:          0 :                         if ( ! call->IsValidCall() )
     207                 :            :                                 {
     208         [ #  # ]:          0 :                                 if ( success )
     209                 :          0 :                                         Weird("successful_RPC_reply_to_invalid_request");
     210                 :            :                                 // We can't process this further, even if
     211                 :            :                                 // it was successful, because the call
     212                 :            :                                 // info won't be fully set up.
     213                 :            :                                 }
     214                 :            : 
     215                 :            :                         else
     216                 :            :                                 {
     217                 :          0 :                                 EventHandlerPtr event;
     218                 :            :                                 Val* reply;
     219         [ #  # ]:          0 :                                 if ( ! RPC_BuildReply(call, success, buf,
     220                 :            :                                                         n, event, reply) )
     221                 :          0 :                                         Weird("bad_RPC");
     222                 :            :                                 else
     223                 :            :                                         {
     224                 :            :                                         Event(event, call->TakeRequestVal(),
     225                 :          0 :                                                 status, reply);
     226                 :            :                                         }
     227                 :            :                                 }
     228                 :            : 
     229                 :          0 :                         RPC_Event(call, status, n);
     230                 :            : 
     231         [ #  # ]:          0 :                         delete calls.RemoveEntry(&h);
     232                 :            :                         }
     233                 :            :                 else
     234                 :            :                         {
     235                 :          0 :                         Weird("unpaired_RPC_response");
     236                 :          0 :                         n = 0;
     237                 :            :                         }
     238                 :            :                 }
     239                 :            : 
     240                 :            :         else
     241                 :          0 :                 Weird("bad_RPC");
     242                 :            : 
     243         [ #  # ]:          0 :         if ( n > 0 )
     244                 :            :                 {
     245                 :            :                 // If it's just padded with zeroes, don't complain.
     246         [ #  # ]:          0 :                 for ( ; n > 0; --n, ++buf )
     247         [ #  # ]:          0 :                         if ( *buf != 0 )
     248                 :          0 :                                 break;
     249                 :            : 
     250         [ #  # ]:          0 :                 if ( n > 0 )
     251                 :          0 :                         Weird("excess_RPC");
     252                 :            :                 }
     253                 :            : 
     254         [ #  # ]:          0 :         else if ( n < 0 )
     255                 :          0 :                 internal_error("RPC underflow");
     256                 :            : 
     257                 :          0 :         return 1;
     258                 :            :         }
     259                 :            : 
     260                 :          0 : void RPC_Interpreter::Timeout()
     261                 :            :         {
     262                 :          0 :         IterCookie* cookie = calls.InitForIteration();
     263                 :            :         RPC_CallInfo* c;
     264                 :            : 
     265         [ #  # ]:          0 :         while ( (c = calls.NextEntry(cookie)) )
     266                 :            :                 {
     267                 :          0 :                 RPC_Event(c, BroEnum::RPC_TIMEOUT, 0);
     268         [ #  # ]:          0 :                 if ( c->IsValidCall() )
     269                 :            :                         {
     270                 :            :                         const u_char* buf;
     271                 :          0 :                         int n = 0;
     272                 :          0 :                         EventHandlerPtr event;
     273                 :            :                         Val* reply;
     274         [ #  # ]:          0 :                         if ( ! RPC_BuildReply(c, 0, buf, n, event, reply) )
     275                 :          0 :                                 Weird("bad_RPC");
     276                 :            :                         else
     277                 :            :                                 {
     278                 :            :                                 Event(event, c->TakeRequestVal(),
     279                 :          0 :                                         BroEnum::RPC_TIMEOUT, reply);
     280                 :            :                                 }
     281                 :            :                         }
     282                 :            :                 }
     283                 :          0 :         }
     284                 :            : 
     285                 :          0 : void RPC_Interpreter::RPC_Event(RPC_CallInfo* c, int status, int reply_len)
     286                 :            :         {
     287         [ #  # ]:          0 :         if ( rpc_call )
     288                 :            :                 {
     289                 :          0 :                 val_list* vl = new val_list;
     290                 :          0 :                 vl->append(analyzer->BuildConnVal());
     291                 :          0 :                 vl->append(new Val(c->Program(), TYPE_COUNT));
     292                 :          0 :                 vl->append(new Val(c->Version(), TYPE_COUNT));
     293                 :          0 :                 vl->append(new Val(c->Proc(), TYPE_COUNT));
     294                 :          0 :                 vl->append(new Val(status, TYPE_COUNT));
     295                 :          0 :                 vl->append(new Val(c->StartTime(), TYPE_TIME));
     296                 :          0 :                 vl->append(new Val(c->CallLen(), TYPE_COUNT));
     297                 :          0 :                 vl->append(new Val(reply_len, TYPE_COUNT));
     298                 :          0 :                 analyzer->ConnectionEvent(rpc_call, vl);
     299                 :            :                 }
     300                 :          0 :         }
     301                 :            : 
     302                 :          0 : void RPC_Interpreter::Weird(const char* msg)
     303                 :            :         {
     304                 :          0 :         analyzer->Weird(msg);
     305                 :          0 :         }
     306                 :            : 
     307                 :            : 
     308                 :            : Contents_RPC::Contents_RPC(Connection* conn, bool orig,
     309                 :          0 :                                 RPC_Interpreter* arg_interp)
     310                 :          0 : : TCP_SupportAnalyzer(AnalyzerTag::Contents_RPC, conn, orig)
     311                 :            :         {
     312                 :          0 :         interp = arg_interp;
     313                 :          0 :         resync = false;
     314                 :          0 :         msg_buf = 0;
     315                 :          0 :         InitBuffer();
     316                 :          0 :         }
     317                 :            : 
     318                 :          0 : void Contents_RPC::Init()
     319                 :            :         {
     320                 :          0 :         TCP_SupportAnalyzer::Init();
     321                 :            : 
     322                 :            :         TCP_Analyzer* tcp =
     323                 :          0 :                 static_cast<TCP_ApplicationAnalyzer*>(Parent())->TCP();
     324         [ #  # ]:          0 :         assert(tcp);
     325                 :            : 
     326                 :            :         resync = (IsOrig() ? tcp->OrigState() : tcp->RespState()) !=
     327         [ #  # ]:          0 :                                                 TCP_ENDPOINT_ESTABLISHED;
     328                 :          0 :         }
     329                 :            : 
     330                 :          0 : void Contents_RPC::InitBuffer()
     331                 :            :         {
     332                 :          0 :         buf_len = 4;
     333                 :            : 
     334                 :            :         // For record marker:
     335         [ #  # ]:          0 :         delete [] msg_buf;
     336                 :          0 :         msg_buf = new u_char[buf_len];
     337                 :            : 
     338                 :          0 :         buf_n = 0;
     339                 :          0 :         last_frag = 0;
     340                 :          0 :         state = RPC_RECORD_MARKER;
     341                 :          0 :         }
     342                 :            : 
     343                 :          0 : Contents_RPC::~Contents_RPC()
     344                 :            :         {
     345 [ #  # ][ #  # ]:          0 :         delete [] msg_buf;
                 [ #  # ]
     346 [ #  # ][ #  # ]:          0 :         }
                 [ #  # ]
     347                 :            : 
     348                 :          0 : void Contents_RPC::Undelivered(int seq, int len, bool orig)
     349                 :            :         {
     350                 :          0 :         TCP_SupportAnalyzer::Undelivered(seq, len, orig);
     351                 :            : 
     352                 :            :         // Re-sync after content gaps.
     353                 :          0 :         InitBuffer();
     354                 :          0 :         resync = true;
     355                 :          0 :         }
     356                 :            : 
     357                 :          0 : void Contents_RPC::DeliverStream(int len, const u_char* data, bool orig)
     358                 :            :         {
     359                 :          0 :         TCP_SupportAnalyzer::DeliverStream(len, data, orig);
     360                 :            : 
     361         [ #  # ]:          0 :         if ( state == RPC_COMPLETE )
     362                 :          0 :                 InitBuffer();
     363                 :            : 
     364                 :            :         // This is an attempt to re-synchronize the stream with RPC
     365                 :            :         // frames after a content gap.  We try to look for the beginning
     366                 :            :         // of an RPC frame, assuming (1) RPC frames begin at packet
     367                 :            :         // boundaries (though they may span over multiple packets) and
     368                 :            :         // (2) the first piece is longer than 12 bytes. (If we see a
     369                 :            :         // piece shorter than 12 bytes, it is likely that it's the
     370                 :            :         // remaining piece of a previous RPC frame, so the code here
     371                 :            :         // skips that piece.)  It then checks if the frame type and length
     372                 :            :         // make any sense, and if so, it assumes that is beginning of
     373                 :            :         // a frame.
     374 [ #  # ][ #  # ]:          0 :         if ( resync && state == RPC_RECORD_MARKER && buf_n == 0 )
                 [ #  # ]
     375                 :            :                 {
     376                 :            :                 // Assuming RPC frames align with packet boundaries ...
     377         [ #  # ]:          0 :                 if ( len < 12 )
     378                 :            :                         {
     379                 :            :                         // Ignore small fragmeents.
     380                 :            :                         if ( len != 1 && DEBUG_rpc_resync )
     381                 :            :                                 {
     382                 :            :                                 // One-byte fragments are likely caused by
     383                 :            :                                 // TCP keep-alive retransmissions.
     384                 :            :                                 DEBUG_MSG("%.6f RPC resync: "
     385                 :            :                                           "discard small pieces: %d\n",
     386                 :            :                                           network_time, len);
     387                 :            :                                 Conn()->Weird(
     388                 :            :                                         fmt("RPC resync: discard %d bytes\n",
     389                 :            :                                                 len));
     390                 :            :                                 }
     391                 :          0 :                         return;
     392                 :            :                         }
     393                 :            : 
     394                 :          0 :                 const u_char* xdata = data;
     395                 :          0 :                 int xlen = len;
     396                 :          0 :                 uint32 frame_len = extract_XDR_uint32(xdata, xlen);
     397                 :          0 :                 uint32 xid = extract_XDR_uint32(xdata, xlen);
     398                 :          0 :                 uint32 frame_type = extract_XDR_uint32(xdata, xlen);
     399                 :            : 
     400   [ #  #  #  # ]:          0 :                 if ( (IsOrig() && frame_type != 0) ||
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
     401                 :            :                      (! IsOrig() && frame_type != 1) ||
     402                 :            :                      frame_len < 16 )
     403                 :            :                         {
     404                 :            :                         // Skip this packet.
     405                 :            :                         if ( DEBUG_rpc_resync )
     406                 :            :                                 {
     407                 :            :                                 DEBUG_MSG("RPC resync: skipping %d bytes\n",
     408                 :            :                                           len);
     409                 :            :                                 }
     410                 :          0 :                         return;
     411                 :            :                         }
     412                 :            : 
     413                 :          0 :                 resync = false;
     414                 :            :                 }
     415                 :            : 
     416                 :            :         int n;
     417 [ #  # ][ #  # ]:          0 :         for ( n = 0; buf_n < buf_len && n < len; ++n )
     418                 :          0 :                 msg_buf[buf_n++] = data[n];
     419                 :            : 
     420         [ #  # ]:          0 :         if ( buf_n < buf_len )
     421                 :            :                 // Haven't filled up the message buffer yet, no more to do.
     422                 :          0 :                 return;
     423                 :            : 
     424   [ #  #  #  # ]:          0 :         switch ( state ) {
     425                 :            :         case RPC_RECORD_MARKER:
     426                 :            :                 { // Have the whole record marker.
     427                 :          0 :                 int prev_frag_len = buf_len - 4;
     428                 :          0 :                 const u_char* buf = &msg_buf[prev_frag_len];
     429                 :          0 :                 int n = 4;
     430                 :            : 
     431                 :          0 :                 uint32 marker = extract_XDR_uint32(buf, n);
     432         [ #  # ]:          0 :                 if ( ! buf )
     433                 :          0 :                         internal_error("inconsistent RPC record marker extraction");
     434                 :            : 
     435 [ #  # ][ #  # ]:          0 :                 if ( prev_frag_len > 0 && last_frag )
     436                 :          0 :                         internal_error("last_frag set but more fragments");
     437                 :            : 
     438                 :          0 :                 last_frag = (marker & 0x80000000) != 0;
     439                 :            : 
     440                 :          0 :                 marker &= 0x7fffffff;
     441                 :            : 
     442         [ #  # ]:          0 :                 if ( prev_frag_len > 0 )
     443                 :            :                         // We're adding another fragment.
     444                 :          0 :                         marker += prev_frag_len;
     445                 :            : 
     446                 :            :                 // Fragment length is now given by marker.  Sanity-check.
     447         [ #  # ]:          0 :                 if ( marker > MAX_RPC_LEN )
     448                 :            :                         {
     449                 :          0 :                         Conn()->Weird("excessive_RPC_len");
     450                 :          0 :                         marker = MAX_RPC_LEN;
     451                 :            :                         }
     452                 :            : 
     453                 :            :                 // The new size is either the full record size (if this
     454                 :            :                 // is the last fragment), or that plus 4 more bytes for
     455                 :            :                 // the next fragment header.
     456         [ #  # ]:          0 :                 int new_size = last_frag ? marker : marker + 4;
     457                 :            : 
     458                 :          0 :                 u_char* tmp = new u_char[new_size];
     459         [ #  # ]:          0 :                 int msg_len = (unsigned int) buf_len < marker ? buf_len : marker;
     460         [ #  # ]:          0 :                 for ( int i = 0; i < msg_len; ++i )
     461                 :          0 :                         tmp[i] = msg_buf[i];
     462                 :            : 
     463         [ #  # ]:          0 :                 delete [] msg_buf;
     464                 :          0 :                 msg_buf = tmp;
     465                 :            : 
     466                 :          0 :                 buf_len = marker;       // we only want to fill to here
     467                 :          0 :                 buf_n = prev_frag_len;  // overwrite this fragment's header
     468                 :            : 
     469                 :          0 :                 state = RPC_MESSAGE_BUFFER;
     470                 :            :                 }
     471                 :          0 :                 break;
     472                 :            : 
     473                 :            :         case RPC_MESSAGE_BUFFER:
     474                 :            :                 { // Have the whole fragment.
     475         [ #  # ]:          0 :                 if ( ! last_frag )
     476                 :            :                         {
     477                 :            :                         // We earlier made sure to leave an extra 4 bytes
     478                 :            :                         // at the end of the buffer - use them now for
     479                 :            :                         // the new fragment header.
     480                 :          0 :                         buf_len += 4;
     481                 :          0 :                         state = RPC_RECORD_MARKER;
     482                 :          0 :                         break;
     483                 :            :                         }
     484                 :            : 
     485         [ #  # ]:          0 :                 if ( ! interp->DeliverRPC(msg_buf, buf_n, IsOrig()) )
     486                 :          0 :                         Conn()->Weird("partial_RPC");
     487                 :            : 
     488                 :          0 :                 state = RPC_COMPLETE;
     489         [ #  # ]:          0 :                 delete [] msg_buf;
     490                 :          0 :                 msg_buf = 0;
     491                 :            :                 }
     492                 :          0 :                 break;
     493                 :            : 
     494                 :            :         case RPC_COMPLETE:
     495                 :          0 :                 internal_error("RPC state inconsistency");
     496                 :            :         }
     497                 :            : 
     498         [ #  # ]:          0 :         if ( n < len )
     499                 :            :                 // More data to munch on.
     500                 :          0 :                 DeliverStream(len - n, data + n, orig);
     501                 :            :         }
     502                 :            : 
     503                 :            : RPC_Analyzer::RPC_Analyzer(AnalyzerTag::Tag tag, Connection* conn,
     504                 :          0 :                                 RPC_Interpreter* arg_interp)
     505                 :          0 : : TCP_ApplicationAnalyzer(tag, conn)
     506                 :            :         {
     507                 :          0 :         interp = arg_interp;
     508                 :            : 
     509   [ #  #  #  # ]:          0 :         if ( Conn()->ConnTransport() == TRANSPORT_UDP )
     510                 :          0 :                 ADD_ANALYZER_TIMER(&RPC_Analyzer::ExpireTimer,
     511                 :            :                         network_time + rpc_timeout, 1, TIMER_RPC_EXPIRE);
     512                 :          0 :         }
     513                 :            : 
     514                 :          0 : RPC_Analyzer::~RPC_Analyzer()
     515                 :            :         {
     516 [ #  # ][ #  # ]:          0 :         delete interp;
                 [ #  # ]
     517 [ #  # ][ #  # ]:          0 :         }
                 [ #  # ]
     518                 :            : 
     519                 :            : void RPC_Analyzer::DeliverPacket(int len, const u_char* data, bool orig,
     520                 :          0 :                                         int seq, const IP_Hdr* ip, int caplen)
     521                 :            :         {
     522                 :          0 :         TCP_ApplicationAnalyzer::DeliverPacket(len, data, orig, seq, ip, caplen);
     523                 :            : 
     524         [ #  # ]:          0 :         if ( orig )
     525                 :            :                 {
     526         [ #  # ]:          0 :                 if ( ! interp->DeliverRPC(data, len, 1) )
     527                 :          0 :                         Weird("bad_RPC");
     528                 :            :                 }
     529                 :            :         else
     530                 :            :                 {
     531         [ #  # ]:          0 :                 if ( ! interp->DeliverRPC(data, len, 0) )
     532                 :          0 :                         Weird("bad_RPC");
     533                 :            :                 }
     534                 :          0 :         }
     535                 :            : 
     536                 :          0 : void RPC_Analyzer::Done()
     537                 :            :         {
     538                 :          0 :         TCP_ApplicationAnalyzer::Done();
     539                 :            : 
     540                 :            :         // This code was replicated in NFS.cc and Portmap.cc, so we factor
     541                 :            :         // it into here.  The semantics have slightly changed - it used
     542                 :            :         // to be we'd always execute interp->Timeout(), but now we only
     543                 :            :         // do for UDP.
     544                 :            : 
     545   [ #  #  #  # ]:          0 :         if ( Conn()->ConnTransport() == TRANSPORT_TCP && TCP() )
                 [ #  # ]
     546                 :            :                 {
     547 [ #  # ][ #  # ]:          0 :                 if ( orig_rpc->State() != RPC_COMPLETE &&
         [ #  # ][ #  # ]
                 [ #  # ]
     548                 :            :                      (TCP()->OrigState() == TCP_ENDPOINT_CLOSED ||
     549                 :            :                       TCP()->OrigPrevState() == TCP_ENDPOINT_CLOSED) &&
     550                 :            :                      // Sometimes things like tcpwrappers will immediately
     551                 :            :                      // close the connection, without any data having been
     552                 :            :                      // transferred.  Don't bother flagging these.
     553                 :            :                      TCP()->Orig()->Size() > 0 )
     554                 :          0 :                         Weird("partial_RPC_request");
     555                 :            :                 }
     556                 :            :         else
     557                 :          0 :                 interp->Timeout();
     558                 :          0 :         }
     559                 :            : 
     560                 :          0 : void RPC_Analyzer::ExpireTimer(double /* t */)
     561                 :            :         {
     562                 :          0 :         Event(connection_timeout);
     563                 :          0 :         sessions->Remove(Conn());
     564                 :          0 :         }
     565                 :            : 
     566                 :            : // The binpac version of interpreter.
     567                 :            : #include "rpc_pac.h"
     568                 :            : 
     569                 :          0 : RPC_UDP_Analyzer_binpac::RPC_UDP_Analyzer_binpac(Connection* conn)
     570                 :          0 : : Analyzer(AnalyzerTag::RPC_UDP_BINPAC, conn)
     571                 :            :         {
     572                 :          0 :         interp = new binpac::SunRPC::RPC_Conn(this);
     573                 :          0 :         ADD_ANALYZER_TIMER(&RPC_UDP_Analyzer_binpac::ExpireTimer,
     574                 :            :                         network_time + rpc_timeout, 1, TIMER_RPC_EXPIRE);
     575                 :          0 :         }
     576                 :            : 
     577                 :          0 : RPC_UDP_Analyzer_binpac::~RPC_UDP_Analyzer_binpac()
     578                 :            :         {
     579 [ #  # ][ #  # ]:          0 :         delete interp;
                 [ #  # ]
     580 [ #  # ][ #  # ]:          0 :         }
                 [ #  # ]
     581                 :            : 
     582                 :          0 : void RPC_UDP_Analyzer_binpac::Done()
     583                 :            :         {
     584                 :          0 :         Analyzer::Done();
     585                 :          0 :         interp->Timeout();
     586                 :          0 :         }
     587                 :            : 
     588                 :          0 : void RPC_UDP_Analyzer_binpac::DeliverPacket(int len, const u_char* data, bool orig, int seq, const IP_Hdr* ip, int caplen)
     589                 :            :         {
     590                 :          0 :         Analyzer::DeliverPacket(len, data, orig, seq, ip, caplen);
     591                 :            :         try
     592                 :            :                 {
     593                 :          0 :                 interp->NewData(orig, data, data + len);
     594                 :            :                 }
     595                 :          0 :         catch ( binpac::Exception &e )
     596                 :            :                 {
     597                 :          0 :                 Weird(fmt("bad_RPC: %s", e.msg().c_str()));
     598                 :            :                 }
     599                 :          0 :         }
     600                 :            : 
     601                 :          0 : void RPC_UDP_Analyzer_binpac::ExpireTimer(double /* t */)
     602                 :            :         {
     603                 :          0 :         Event(connection_timeout);
     604                 :          0 :         sessions->Remove(Conn());
     605 [ +  - ][ +  - ]:          6 :         }

Generated by: LCOV version 1.8