Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | File List | Namespace Members | Class Members | File Members

BackDoor.cc

Go to the documentation of this file.
00001 // $Id: BackDoor.cc,v 1.6 2005/09/13 05:22:49 vern Exp $
00002 //
00003 // Copyright (c) 1999, 2000, 2001, 2002
00004 //      The Regents of the University of California.  All rights reserved.
00005 //
00006 // Redistribution and use in source and binary forms, with or without
00007 // modification, are permitted provided that: (1) source code distributions
00008 // retain the above copyright notice and this paragraph in its entirety, (2)
00009 // distributions including binary code include the above copyright notice and
00010 // this paragraph in its entirety in the documentation or other materials
00011 // provided with the distribution, and (3) all advertising materials mentioning
00012 // features or use of this software display the following acknowledgement:
00013 // ``This product includes software developed by the University of California,
00014 // Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
00015 // the University nor the names of its contributors may be used to endorse
00016 // or promote products derived from this software without specific prior
00017 // written permission.
00018 // THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
00019 // WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
00020 // MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
00021 
00022 #include "config.h"
00023 
00024 #include "BackDoor.h"
00025 #include "Event.h"
00026 #include "Net.h"
00027 #include "TCP.h"
00028 
00029 BackDoorEndpoint::BackDoorEndpoint(TCP_Endpoint* e)
00030 : TCP_EndpointAnalyzer(e)
00031         {
00032         is_partial = 0;
00033         max_top_seq = 0;
00034 
00035         rlogin_checking_done = 0;
00036         rlogin_string_separator_pos = 0;
00037         rlogin_num_null = 0;
00038         rlogin_slash_seen = 0;
00039 
00040         num_pkts = num_8k0_pkts = num_8k4_pkts =
00041                 num_lines = num_normal_lines = num_bytes = num_7bit_ascii = 0;
00042         }
00043 
00044 #define NORMAL_LINE_LENGTH 80
00045 
00046 #define TELNET_IAC 255
00047 #define IS_TELNET_NEGOTIATION_CMD(c) ((c) >= 251 && (c) <= 254)
00048 
00049 #define DEFAULT_MTU 512
00050 
00051 #define RLOGIN_MAX_SIGNATURE_LENGTH 256
00052 
00053 void BackDoorEndpoint::FinalCheckForRlogin()
00054         {
00055         if ( ! rlogin_checking_done )
00056                 {
00057                 rlogin_checking_done = 1;
00058 
00059                 if ( rlogin_num_null > 0 )
00060                         RloginSignatureFound(0);
00061                 }
00062         }
00063 
00064 int BackDoorEndpoint::DataSent(double /* t */, int seq,
00065                                 int len, int caplen, const u_char* data,
00066                                 const IP_Hdr* /* ip */,
00067                                 const struct tcphdr* /* tp */)
00068         {
00069         if ( caplen < len )
00070                 len = caplen;
00071 
00072         if ( len <= 0 )
00073                 return 0;
00074 
00075         if ( Endpoint()->state == TCP_PARTIAL )
00076                 is_partial = 1;
00077 
00078         int ack = Endpoint()->AckSeq() - Endpoint()->StartSeq();
00079         int top_seq = seq + len;
00080 
00081         if ( top_seq <= ack || top_seq <= max_top_seq )
00082                 // There is no new data in this packet.
00083                 return 0;
00084 
00085         if ( rlogin_signature_found )
00086                 CheckForRlogin(seq, len, data);
00087 
00088         if ( telnet_signature_found )
00089                 CheckForTelnet(seq, len, data);
00090 
00091         if ( ssh_signature_found )
00092                 CheckForSSH(seq, len, data);
00093 
00094         if ( ftp_signature_found )
00095                 CheckForFTP(seq, len, data);
00096 
00097         if ( root_backdoor_signature_found )
00098                 CheckForRootBackdoor(seq, len, data);
00099 
00100         if ( napster_signature_found )
00101                 CheckForNapster(seq, len, data);
00102 
00103         if ( gnutella_signature_found )
00104                 CheckForGnutella(seq, len, data);
00105 
00106         if ( kazaa_signature_found )
00107                 CheckForKazaa(seq, len, data);
00108 
00109         if ( http_signature_found || http_proxy_signature_found )
00110                 CheckForHTTP(seq, len, data);
00111 
00112         if ( smtp_signature_found )
00113                 CheckForSMTP(seq, len, data);
00114 
00115         if ( irc_signature_found )
00116                 CheckForIRC(seq, len, data);
00117 
00118         if ( gaobot_signature_found )
00119                 CheckForGaoBot(seq, len, data);
00120 
00121         max_top_seq = top_seq;
00122 
00123         return 1;
00124         }
00125 
00126 RecordVal* BackDoorEndpoint::BuildStats()
00127         {
00128         RecordVal* stats = new RecordVal(backdoor_endp_stats);
00129 
00130         stats->Assign(0, new Val(is_partial, TYPE_BOOL));
00131         stats->Assign(1, new Val(num_pkts, TYPE_COUNT));
00132         stats->Assign(2, new Val(num_8k0_pkts, TYPE_COUNT));
00133         stats->Assign(3, new Val(num_8k4_pkts, TYPE_COUNT));
00134         stats->Assign(4, new Val(num_lines, TYPE_COUNT));
00135         stats->Assign(5, new Val(num_normal_lines, TYPE_COUNT));
00136         stats->Assign(6, new Val(num_bytes, TYPE_COUNT));
00137         stats->Assign(7, new Val(num_7bit_ascii, TYPE_COUNT));
00138 
00139         return stats;
00140         }
00141 
00142 void BackDoorEndpoint::CheckForRlogin(int seq, int len, const u_char* data)
00143         {
00144         if ( rlogin_checking_done )
00145                 return;
00146 
00147         // Looking for pattern:
00148         //      <null>string<null>string<null>string/string<null>
00149         // where all string's are non-empty 7-bit-ascii string
00150         //
00151         // To avoid having to reassemble, we keep testing each byte until
00152         // one of the following happens:
00153         //
00154         //      - A gap in sequence number occurs
00155         //      - Four null's have been found
00156         //      - The number of bytes we examined reaches RLOGIN_MAX_SIGNATURE_LENGTH
00157         //      - An empty or non-7-bit-ascii string is found
00158         //
00159         if ( seq == 1 )
00160                 { // Check if first byte is a NUL.
00161                 if ( data[0] == 0 )
00162                         {
00163                         rlogin_num_null = 1;
00164 
00165                         if ( ! Endpoint()->IsOrig() )
00166                                 {
00167                                 RloginSignatureFound(len);
00168                                 return;
00169                                 }
00170 
00171                         rlogin_string_separator_pos = 1;
00172 
00173                         ++seq;  // move past the byte
00174                         ++data;
00175                         --len;
00176                         }
00177                 else
00178                         {
00179                         rlogin_checking_done = 1;
00180                         return;
00181                         }
00182                 }
00183 
00184         if ( seq > max_top_seq && max_top_seq != 0 )
00185                 { // A gap! Since we don't reassemble things, stop now.
00186                 RloginSignatureFound(0);
00187                 return;
00188                 }
00189 
00190         if ( seq + len <= max_top_seq )
00191                 return; // nothing new
00192 
00193         if ( seq < max_top_seq )
00194                 { // trim to just the new data
00195                 int delta = max_top_seq - seq;
00196                 seq += delta;
00197                 data += delta;
00198                 len -= delta;
00199                 }
00200 
00201         // Search for rlogin signature.
00202         for ( int i = 0; i < len && rlogin_num_null < 4; ++i )
00203                 {
00204                 if ( data[i] == 0 )
00205                         {
00206                         if ( i + seq == rlogin_string_separator_pos + 1 )
00207                                 { // Empty string found.
00208                                 rlogin_checking_done = 1;
00209                                 return;
00210                                 }
00211                         else
00212                                 {
00213                                 rlogin_string_separator_pos = i + seq;
00214                                 ++rlogin_num_null;
00215                                 }
00216                         }
00217 
00218                 else if ( data[i] == '/' )
00219                         {
00220                         if ( rlogin_num_null == 3 )
00221                                 {
00222                                 if ( i + seq == rlogin_string_separator_pos + 1 )
00223                                         { // Empty terminal type.
00224                                         rlogin_checking_done = 1;
00225                                         return;
00226                                         }
00227 
00228                                 rlogin_string_separator_pos = i + seq;
00229                                 rlogin_slash_seen = 1;
00230                                 }
00231                         }
00232 
00233                 else if ( data[i] >= 128 )
00234                         { // Non-7-bit-ascii
00235                         rlogin_checking_done = 1;
00236                         return;
00237                         }
00238                 }
00239 
00240         if ( rlogin_num_null == 4 )
00241                 {
00242                 if ( rlogin_slash_seen )
00243                         RloginSignatureFound(0);
00244                 else
00245                         rlogin_checking_done = 1;
00246 
00247                 return;
00248                 }
00249 
00250         if ( seq + len > RLOGIN_MAX_SIGNATURE_LENGTH )
00251                 { // We've waited for too long
00252                 RloginSignatureFound(0);
00253                 return;
00254                 }
00255         }
00256 
00257 void BackDoorEndpoint::RloginSignatureFound(int len)
00258         {
00259         if ( rlogin_checking_done )
00260                 return;
00261 
00262         rlogin_checking_done = 1;
00263 
00264         val_list* vl = new val_list;
00265         vl->append(Conn()->BuildConnVal());
00266         vl->append(new Val(Endpoint()->IsOrig(), TYPE_BOOL));
00267         vl->append(new Val(rlogin_num_null, TYPE_COUNT));
00268         vl->append(new Val(len, TYPE_COUNT));
00269 
00270         Conn()->ConnectionEvent(rlogin_signature_found, vl);
00271         }
00272 
00273 void BackDoorEndpoint::CheckForTelnet(int /* seq */, int len, const u_char* data)
00274         {
00275         if ( len >= 3 &&
00276              data[0] == TELNET_IAC && IS_TELNET_NEGOTIATION_CMD(data[1]) )
00277                 {
00278                 TelnetSignatureFound(len);
00279                 return;
00280                 }
00281 
00282         // Note, we do the analysis per-packet rather than on the reassembled
00283         // stream.  This is a lot more efficient as then we don't need to
00284         // do stream reassembly; but it's potentially less accurate, and
00285         // subject to evasion.  *But*: backdoor detection is inherently
00286         // subject to a wide variety of evasion, so allowing this form
00287         // (which is a pain to exploit) costs little.
00288 
00289         num_bytes += len;
00290 
00291         int last_char = 0;
00292         int offset = 0; // where we consider the latest line to have begun
00293         int option_length = 0; // length of options in a line
00294 
00295         for ( int i = 0; i < len; ++i )
00296                 {
00297                 unsigned int c = data[i];
00298 
00299                 if ( c == '\n' && last_char == '\r' )
00300                         {
00301                         // Compress CRLF to just one line termination.
00302                         last_char = c;
00303                         continue;
00304                         }
00305 
00306                 if ( c == '\n' || c == '\r' )
00307                         {
00308                         ++num_lines;
00309 
00310                         if ( i - offset - option_length <= NORMAL_LINE_LENGTH )
00311                                 ++num_normal_lines;
00312 
00313                         option_length = 0;
00314                         offset = i;
00315                         }
00316 
00317                 else if ( c == TELNET_IAC )
00318                         {
00319                         ++option_length;
00320                         --num_bytes;
00321 
00322                         if ( ++i < len )
00323                                 {
00324                                 unsigned int code = data[i];
00325                                 if ( code == TELNET_IAC )
00326                                         // Escaped IAC.
00327                                         last_char = code;
00328 
00329                                 else if ( code >= 251 && code <= 254 )
00330                                         { // 3-byte option: ignore next byte
00331                                         ++i;
00332                                         option_length += 2;
00333                                         num_bytes -= 2;
00334                                         }
00335 
00336                                 else
00337                                         // XXX: We don't deal with sub option for simplicity
00338                                         // although we SHOULD!
00339                                         {
00340                                         ++option_length;
00341                                         --num_bytes;
00342                                         }
00343                                 }
00344                         continue;
00345                         }
00346 
00347                 else if ( c != 0 && c < 128 )
00348                         ++num_7bit_ascii;
00349 
00350                 last_char = c;
00351                 }
00352         }
00353 
00354 void BackDoorEndpoint::TelnetSignatureFound(int len)
00355         {
00356         val_list* vl = new val_list;
00357         vl->append(Conn()->BuildConnVal());
00358         vl->append(new Val(Endpoint()->IsOrig(), TYPE_BOOL));
00359         vl->append(new Val(len, TYPE_COUNT));
00360 
00361         Conn()->ConnectionEvent(telnet_signature_found, vl);
00362         }
00363 
00364 void BackDoorEndpoint::CheckForSSH(int seq, int len, const u_char* data)
00365         {
00366         if ( seq == 1 && CheckForString("SSH-", data, len) && len > 4 &&
00367              (data[4] == '1' || data[4] == '2') )
00368                 {
00369                 SignatureFound(ssh_signature_found, 1);
00370                 return;
00371                 }
00372 
00373         // Check for length pattern.
00374 
00375         if ( seq < max_top_seq || max_top_seq == 0 )
00376                 // Retransmission involved, or first pkt => size info useless.
00377                 return;
00378 
00379         if ( seq > max_top_seq )
00380                 { // Estimate number of packets in the sequence gap
00381                 int gap = seq - max_top_seq;
00382                 num_pkts += int((gap + DEFAULT_MTU - 1) / DEFAULT_MTU);
00383                 }
00384 
00385         ++num_pkts;
00386 
00387         // According to the spec:
00388         //      SSH 1.x pkts have size 8k+4
00389         //      SSH 2.x pkts have size 8k >= 16 (most cipher blocks are 8n)
00390         if ( len <= 127 )
00391                 switch ( len & 7 ) {
00392                 case 0:
00393                         if ( len >= 16 )
00394                                 ++num_8k0_pkts;
00395                         break;
00396 
00397                 case 4:
00398                         ++num_8k4_pkts;
00399                         break;
00400                 }
00401         else
00402                 { // len is likely to be some MTU.
00403                 }
00404         }
00405 
00406 void BackDoorEndpoint::CheckForRootBackdoor(int seq, int len, const u_char* data)
00407         {
00408         // Check for root backdoor signature: an initial payload of
00409         // exactly "# ".
00410         if ( seq == 1 && len == 2 && ! Endpoint()->IsOrig() &&
00411              data[0] == '#' && data[1] == ' ' )
00412                 SignatureFound(root_backdoor_signature_found);
00413         }
00414 
00415 void BackDoorEndpoint::CheckForFTP(int seq, int len, const u_char* data)
00416         {
00417         // Check for FTP signature
00418         //
00419         // Currently, the signatures include: "220 ", "220-"
00420         //
00421         // For a day's worth of LBNL FTP activity (7,229 connections),
00422         // the distribution of the code in the first line returned by
00423         // the server (the lines always began with a code) is:
00424         //
00425         //      220: 6685
00426         //      421: 535
00427         //      226: 7
00428         //      426: 1
00429         //      200: 1
00430         //
00431         // The 421's are all "host does not have access" or "timeout" of
00432         // some form, so it's not big deal with we miss them (if that helps
00433         // keep down the false positives).
00434 
00435         if ( seq != 1 || Endpoint()->IsOrig() || len < 4 )
00436                 return;
00437 
00438         if ( CheckForString("220", data, len) &&
00439              (data[3] == ' ' || data[3] == '-') )
00440                 SignatureFound(ftp_signature_found);
00441 
00442         else if ( CheckForString("421", data, len) &&
00443                   (data[3] == '-' || data[3] == ' ') )
00444                 SignatureFound(ftp_signature_found);
00445         }
00446 
00447 void BackDoorEndpoint::CheckForNapster(int seq, int len, const u_char* data)
00448         {
00449         // Check for Napster signature "GETfoobar" or "SENDfoobar" where
00450         // "foobar" is the Napster handle associated with the request
00451         // (so pretty much any arbitrary identifier, but sent adjacent
00452         // to the GET or SEND with no intervening whitespace; but also
00453         // sent in a separate packet.
00454 
00455         if ( seq != 1 || ! Endpoint()->IsOrig() )
00456                 return;
00457 
00458         if ( len == 3 && CheckForString("GET", data, len) )
00459                 // GETfoobar.
00460                 SignatureFound(napster_signature_found);
00461 
00462         else if ( len == 4 && CheckForString("SEND", data, len) )
00463                 // SENDfoobar.
00464                 SignatureFound(napster_signature_found);
00465         }
00466 
00467 void BackDoorEndpoint::CheckForSMTP(int seq, int len, const u_char* data)
00468         {
00469         const char* smtp_handshake[] = { "HELO", "EHLO", 0 };
00470 
00471         if ( seq != 1 )
00472                 return;
00473 
00474         if ( CheckForStrings(smtp_handshake, data, len) )
00475                 SignatureFound(smtp_signature_found);
00476         }
00477 
00478 void BackDoorEndpoint::CheckForIRC(int seq, int len, const u_char* data)
00479         {
00480         // Look for any of the following exchange in the initial (15) packets
00481         // of a connection.
00482         //
00483         // WHO  : (C->S) client query for name
00484         // PING : (S->C) test for presence of client at other end
00485         // PONG : (C->S) reply to PING message
00486         // MODE : (C->S)
00487         // IRCX : (C->S) ?? Not in RFC
00488         // NICK : (C->S) user nickname
00489 
00490         const char* irc_indicator[] = {
00491                 "WHO", "PING", "PONG", "NODE", "IRCX", "NICK", 0
00492         };
00493 
00494         if ( num_pkts > 15 || len < 5 )
00495                 return;
00496 
00497         if ( CheckForStrings(irc_indicator, data, len) )
00498                 SignatureFound(irc_signature_found);
00499         }
00500 
00501 void BackDoorEndpoint::CheckForGnutella(int seq, int len, const u_char* data)
00502         {
00503         // After connecting to the server, the connecting client says:
00504         //
00505         //              GNUTELLA CONNECT/<version>\n\n
00506         //
00507         // The accepting server responds:
00508         //
00509         //              GNUTELLA OK\n\n
00510         //
00511         // We find checking the first 8 bytes suffices, and that will
00512         // also catch variants that use something other than "CONNECT".
00513 
00514         if ( seq == 1 && CheckForString("GNUTELLA ", data, len) )
00515                 SignatureFound(gnutella_signature_found);
00516         }
00517 
00518 void BackDoorEndpoint::CheckForGaoBot(int seq, int len, const u_char* data)
00519         {
00520         if ( seq == 1 && CheckForString("220 Bot Server (Win32)", data, len) )
00521                 SignatureFound(gaobot_signature_found);
00522         }
00523 
00524 void BackDoorEndpoint::CheckForKazaa(int seq, int len, const u_char* data)
00525         {
00526         // *Some*, though not all, KaZaa connections begin with:
00527         //
00528         //              GIVE<space>
00529 
00530         if ( seq == 1 && CheckForString("GIVE ", data, len) )
00531                 SignatureFound(kazaa_signature_found);
00532         }
00533 
00534 
00535 int is_http_whitespace(const u_char ch)
00536         {
00537         return ! isprint(ch) || isspace(ch);
00538         }
00539 
00540 int skip_http_whitespace(const u_char* data, int len, int max)
00541         {
00542         int k;
00543         for ( k = 0; k < len; ++k )
00544                 {
00545                 if ( ! is_http_whitespace(data[k]) )
00546                         break;
00547 
00548                 // Here we do not go beyond CR -- this is OK for
00549                 // processing first line of HTTP requests. However, it
00550                 // cannot be used to process multiple-line headers.
00551 
00552                 if ( data[k] == '\015' || k == max )
00553                         return -1;
00554                 }
00555 
00556         return k < len ? k : -1;
00557         }
00558 
00559 int is_absolute_url(const u_char* data, int len)
00560         {
00561         // Look for '://' in the URL.
00562         const char* abs_url_sig = "://";
00563         const char* abs_url_sig_pos = abs_url_sig;
00564 
00565         // Warning: the following code is NOT general for any signature string,
00566         // but only works for specific strings like "://".
00567 
00568         for ( int pos = 0; pos < len; ++pos )
00569                 {
00570                 if ( *abs_url_sig_pos == '\0' )
00571                         return 1;
00572 
00573                 if ( data[pos] == *abs_url_sig_pos )
00574                         ++abs_url_sig_pos;
00575 
00576                 else
00577                         {
00578                         if ( is_http_whitespace(data[pos]) )
00579                                 return 0;
00580 
00581                         abs_url_sig_pos = abs_url_sig;
00582                         if ( *abs_url_sig != '\0' &&
00583                              *abs_url_sig_pos == data[pos] )
00584                                 ++abs_url_sig_pos;
00585                         }
00586                 }
00587 
00588         return *abs_url_sig_pos == '\0';
00589         }
00590 
00591 void BackDoorEndpoint::CheckForHTTP(int seq, int len, const u_char* data)
00592         {
00593         // According to the RFC, we should look for
00594         // '<method> SP <url> SP HTTP/<version> CR LF'
00595         // where:
00596         //
00597         //      <method> = GET | HEAD | POST
00598         //
00599         // (i.e., HTTP 1.1 methods are ignored for now)
00600         // <version> = 1.0 | 1.1.
00601         //
00602         // However, this is probably too restrictive to catch 'non-standard'
00603         // requests. Instead, we look for certain methods only in the first
00604         // line of the first packet only.
00605         //
00606         // "The method is case-sensitive." -- RFC 2616
00607 
00608         const char* http_method[] = { "GET", "HEAD", "POST", 0 };
00609 
00610         if ( seq != 1 )
00611                 return; // first packet only
00612 
00613         // Pick up the method.
00614         int pos = skip_http_whitespace (data, len, 0);
00615         if ( pos < 0 )
00616                 return;
00617 
00618         int method;
00619         for ( method = 0; http_method[method]; ++method )
00620                 {
00621                 const char* s = http_method[method];
00622                 int i;
00623                 for ( i = pos; i < len; ++i, ++s )
00624                         if ( data[i] != *s )
00625                                 break;
00626 
00627                 if ( *s == '\0' )
00628                         {
00629                         pos = i;
00630                         break;
00631                         }
00632                 }
00633 
00634         if ( ! http_method[method] )
00635                 return;
00636 
00637         if ( pos >= len || ! is_http_whitespace(data[pos]) )
00638                 return;
00639 
00640         if ( http_signature_found )
00641                 SignatureFound(http_signature_found);
00642 
00643         if ( http_proxy_signature_found )
00644                 {
00645                 const u_char* rest = data + pos;
00646                 int rest_len = len - pos;
00647 
00648                 pos = skip_http_whitespace(rest, rest_len, rest_len);
00649 
00650                 if ( pos >= 0 )
00651                         CheckForHTTPProxy(seq, rest_len - pos, rest + pos);
00652                 }
00653         }
00654 
00655 void BackDoorEndpoint::CheckForHTTPProxy(int /* seq */, int len,
00656                                         const u_char* data)
00657         {
00658         // Proxy ONLY accepts absolute URI's: "The absoluteURI form is
00659         // REQUIRED when the request is being made to a proxy." -- RFC 2616
00660 
00661         if ( is_absolute_url(data, len) )
00662                 SignatureFound(http_proxy_signature_found);
00663         }
00664 
00665 
00666 void BackDoorEndpoint::SignatureFound(EventHandlerPtr e, int do_orig)
00667         {
00668         val_list* vl = new val_list;
00669         vl->append(Conn()->BuildConnVal());
00670 
00671         if ( do_orig )
00672                 vl->append(new Val(Endpoint()->IsOrig(), TYPE_BOOL));
00673 
00674         Conn()->ConnectionEvent(e, vl);
00675         }
00676 
00677 
00678 int BackDoorEndpoint::CheckForStrings(const char** strs,
00679                                         const u_char* data, int len)
00680         {
00681         for ( ; *strs; ++strs )
00682                 if ( CheckForString(*strs, data, len) )
00683                         return 1;
00684 
00685         return 0;
00686         }
00687 
00688 int BackDoorEndpoint::CheckForString(const char* str,
00689                                         const u_char* data, int len)
00690         {
00691         for ( ; len > 0 && *str; --len, ++data, ++str )
00692                 if ( *str != *data )
00693                         return 0;
00694 
00695         return *str == 0;
00696         }
00697 
00698 
00699 BackDoorAnalyzer::BackDoorAnalyzer(TCP_Connection* c)
00700 : TCP_Analyzer(c)
00701         {
00702         orig_endp = new BackDoorEndpoint(conn->Orig());
00703         resp_endp = new BackDoorEndpoint(conn->Resp());
00704 
00705         timeout = backdoor_stat_period;
00706         backoff = backdoor_stat_backoff;
00707 
00708         timer_mgr->Add(new BackDoorTimer(network_time + timeout, this));
00709         }
00710 
00711 BackDoorAnalyzer::~BackDoorAnalyzer()
00712         {
00713         Done();
00714 
00715         Unref(orig_endp);
00716         Unref(resp_endp);
00717         }
00718 
00719 void BackDoorAnalyzer::Done()
00720         {
00721         if ( ! done )
00722                 {
00723                 orig_endp->FinalCheckForRlogin();
00724                 resp_endp->FinalCheckForRlogin();
00725 
00726                 if ( ! Conn()->Skipping() )
00727                         StatEvent();
00728 
00729                 RemoveEvent();
00730                 done = 1;
00731                 }
00732         }
00733 
00734 void BackDoorAnalyzer::StatTimer(double t, int is_expire)
00735         {
00736         if ( done || Conn()->Skipping() )
00737                 return;
00738 
00739         StatEvent();
00740 
00741         if ( ! is_expire )
00742                 {
00743                 timeout *= backoff;
00744                 timer_mgr->Add(new BackDoorTimer(t + timeout, this));
00745                 }
00746         }
00747 
00748 void BackDoorAnalyzer::StatEvent()
00749         {
00750         val_list* vl = new val_list;
00751         vl->append(Conn()->BuildConnVal());
00752         vl->append(orig_endp->BuildStats());
00753         vl->append(resp_endp->BuildStats());
00754 
00755         Conn()->ConnectionEvent(backdoor_stats, vl);
00756         }
00757 
00758 void BackDoorAnalyzer::RemoveEvent()
00759         {
00760         val_list* vl = new val_list;
00761         vl->append(Conn()->BuildConnVal());
00762 
00763         Conn()->ConnectionEvent(backdoor_remove_conn, vl);
00764         }
00765 
00766 BackDoorTimer::BackDoorTimer(double t, BackDoorAnalyzer* a)
00767 : Timer(t, TIMER_BACKDOOR)
00768         {
00769         analyzer = a;
00770         Ref(a);
00771         }
00772 
00773 BackDoorTimer::~BackDoorTimer()
00774         {
00775         Unref(analyzer);
00776         }
00777 
00778 void BackDoorTimer::Dispatch(double t, int is_expire)
00779         {
00780         analyzer->StatTimer(t, is_expire);
00781         }

Generated on Wed Sep 14 02:55:57 2005 for bro_docs by doxygen 1.3.5