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

TCP.cc

Go to the documentation of this file.
00001 // $Id: TCP.cc,v 1.15 2005/09/08 07:42:11 vern Exp $
00002 //
00003 // Copyright (c) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003
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 
00023 #include "Active.h"
00024 #include "File.h"
00025 #include "TCP.h"
00026 #include "TCP_Rewriter.h"
00027 #include "OSFinger.h"
00028 #include "Event.h"
00029 
00030 
00031 // The following are not included in all systems' tcp.h.
00032 
00033 #ifndef TH_ECE
00034 #define TH_ECE  0x40
00035 #endif
00036 
00037 #ifndef TH_CWR
00038 #define TH_CWR  0x80
00039 #endif
00040 
00041 
00042 #define TOO_LARGE_SEQ_DELTA 1048576
00043 
00044 
00045 TCP_Connection::TCP_Connection(NetSessions* s, HashKey* k, double t,
00046                 const ConnID* id, const struct tcphdr* tp)
00047 : Connection(s, k, t, id)
00048         {
00049         // Set a timer to eventually time out this connection.
00050         ADD_TIMER(&TCP_Connection::ExpireTimer, t + tcp_SYN_timeout, 0,
00051                         TIMER_TCP_EXPIRE);
00052 
00053         deferred_gen_event = close_deferred = 0;
00054         analyzer = 0;
00055 
00056         if ( ! (tp->th_flags & TH_SYN) || (tp->th_flags & TH_ACK) )
00057                 is_partial = 1;
00058         else
00059                 is_partial = 0;
00060 
00061         // By default, if it's a TCP port 80 FIN packet, don't record its
00062         // contents.  Eliminating these (unless we're doing HTTP analysis)
00063         // cuts the save file size by about a factor of two, since often
00064         // HTTP FIN packets have most of the server reply in them.
00065         if ( (tp->th_flags & TH_FIN) && ntohs(resp_port) == 80 )
00066                 record_contents = 0;
00067 
00068         seen_first_ACK = 0;
00069 
00070         trace_rewriter = 0;
00071         src_pkt_writer = 0;
00072         }
00073 
00074 void TCP_Connection::Init()
00075         {
00076         orig = new TCP_Endpoint(this, 1);
00077         resp = new TCP_Endpoint(this, 0);
00078 
00079         orig->SetPeer(resp);
00080         resp->SetPeer(orig);
00081 
00082         BuildEndpoints();
00083 
00084         // Can't put this in construction because RewritingTrace() is virtual.
00085         if ( transformed_pkt_dump && RewritingTrace() )
00086                 { // rewrite TCP trace
00087                 trace_rewriter =
00088                         new TCP_Rewriter(this, transformed_pkt_dump,
00089                                                 transformed_pkt_dump_MTU,
00090                                                 requires_trace_commitment);
00091                 }
00092 
00093         if ( dump_selected_source_packets )
00094                 {
00095                 if ( source_pkt_dump )
00096                         src_pkt_writer =
00097                                 new TCP_SourcePacketWriter(this, source_pkt_dump);
00098                 else if ( transformed_pkt_dump )
00099                         src_pkt_writer =
00100                                 new TCP_SourcePacketWriter(this, transformed_pkt_dump);
00101                 }
00102         }
00103 
00104 TCP_Connection::~TCP_Connection()
00105         {
00106         delete orig;
00107         delete resp;
00108         delete trace_rewriter;
00109         delete src_pkt_writer;
00110         }
00111 
00112 void TCP_Connection::Done()
00113         {
00114         if ( trace_rewriter )
00115                 trace_rewriter->Done();
00116 
00117         if ( tcp_match_undelivered )
00118                 {
00119                 orig->MatchUndeliveredData();
00120                 resp->MatchUndeliveredData();
00121                 }
00122 
00123         FinishEndpointMatcher();
00124 
00125         if ( connection_pending && is_active && ! BothClosed() )
00126                 Event(connection_pending);
00127 
00128         while ( analyzer )
00129                 {
00130                 TCP_Analyzer* a = analyzer;
00131                 analyzer = analyzer->NextAnalyzer();
00132                 a->Done();
00133                 Unref(a);
00134                 }
00135 
00136         finished = 1;
00137         }
00138 
00139 void TCP_Connection::AddAnalyzer(TCP_Analyzer* a)
00140         {
00141         a->AddAnalyzer(analyzer);
00142         analyzer = a;
00143 
00144         // Don't Ref(a) - when this connection goes away, we want
00145         // the analyzer to go away, too (unless somewhere else it was
00146         // Ref()'d).
00147         }
00148 
00149 void TCP_Connection::AnalyzerDone()
00150         {
00151         TCP_Analyzer* a = analyzer;
00152 
00153         while ( a )
00154                 {
00155                 TCP_Analyzer* b = a;
00156                 a = a->NextAnalyzer();
00157                 b->Done();
00158                 }
00159 
00160         // Don't Unref(b) - it'll be done when this connection goes away.
00161         }
00162 
00163 void TCP_Connection::BuildEndpoints()
00164         {
00165         }
00166 
00167 Val* TCP_Connection::BuildSYNPacketVal(int is_orig,
00168                                 const IP_Hdr* ip, const struct tcphdr* tcp)
00169         {
00170         int winscale = -1;
00171         int MSS = 0;
00172         int SACK = 0;
00173 
00174         // Parse TCP options.
00175         u_char* options = (u_char*) tcp + sizeof(struct tcphdr);
00176         u_char* opt_end = (u_char*) tcp + tcp->th_off * 4;
00177 
00178         while ( options < opt_end )
00179                 {
00180                 unsigned int opt = options[0];
00181 
00182                 if ( opt == TCPOPT_EOL )
00183                         // All done - could flag if more junk left over ....
00184                         break;
00185 
00186                 if ( opt == TCPOPT_NOP )
00187                         {
00188                         ++options;
00189                         continue;
00190                         }
00191 
00192                 if ( options + 1 >= opt_end )
00193                         // We've run off the end, no room for the length.
00194                         break;
00195 
00196                 unsigned int opt_len = options[1];
00197 
00198                 if ( options + opt_len > opt_end )
00199                         // No room for rest of option.
00200                         break;
00201 
00202                 if ( opt_len == 0 )
00203                         // Trashed length field.
00204                         break;
00205 
00206                 switch ( opt ) {
00207                 case TCPOPT_SACK_PERMITTED:
00208                         SACK = 1;
00209                         break;
00210 
00211                 case TCPOPT_MAXSEG:
00212                         if ( opt_len < 4 )
00213                                 break;  // bad length
00214 
00215                         MSS = (options[2] << 8) | options[3];
00216                         break;
00217 
00218                 case 3: // TCPOPT_WSCALE
00219                         if ( opt_len < 3 )
00220                                 break;  // bad length
00221 
00222                         winscale = options[2];
00223                         break;
00224 
00225                 default:        // just skip over
00226                         break;
00227                 }
00228 
00229                 options += opt_len;
00230                 }
00231 
00232         RecordVal* v = new RecordVal(SYN_packet);
00233 
00234         v->Assign(0, new Val(is_orig, TYPE_BOOL));
00235         v->Assign(1, new Val(int(ip->DF()), TYPE_BOOL));
00236         v->Assign(2, new Val(int(ip->TTL()), TYPE_INT));
00237         v->Assign(3, new Val((ip->TotalLen()), TYPE_INT));
00238         v->Assign(4, new Val(ntohs(tcp->th_win), TYPE_INT));
00239         v->Assign(5, new Val(winscale, TYPE_INT));
00240         v->Assign(6, new Val(MSS, TYPE_INT));
00241         v->Assign(7, new Val(SACK, TYPE_BOOL));
00242 
00243         return v;
00244         }
00245 
00246 RecordVal* TCP_Connection::BuildOSVal(int is_orig, const IP_Hdr* ip,
00247                         const struct tcphdr* tcp, uint32 tcp_hdr_len)
00248         {
00249         if ( ! is_orig )
00250                 // Later we might use SYN-ACK fingerprinting here.
00251                 return 0;
00252 
00253         // Passive OS fingerprinting wants to know a lot about IP and TCP
00254         // options: how many options there are, and in which order.
00255         int winscale = 0;
00256         int MSS = 0;
00257         int optcount = 0;
00258         uint32 quirks = 0;
00259         uint32 tstamp = 0;
00260         uint8 op[MAXOPT];
00261 
00262         if ( ip->HdrLen() > 20 )
00263                 quirks |= QUIRK_IPOPT;
00264 
00265         if ( ip->IP_ID() == 0 )
00266                 quirks |= QUIRK_ZEROID;
00267 
00268         if ( tcp->th_seq == 0 )
00269                 quirks |= QUIRK_SEQ0;
00270 
00271         if ( tcp->th_seq == tcp->th_ack )
00272                 quirks |= QUIRK_SEQEQ;
00273 
00274         if ( tcp->th_flags & ~(TH_SYN|TH_ACK|TH_RST|TH_ECE|TH_CWR) )
00275                 quirks |= QUIRK_FLAGS;
00276 
00277         if ( ip->TotalLen() - ip->HdrLen() - tcp_hdr_len > 0 )
00278                 quirks |= QUIRK_DATA;   // SYN with data
00279 
00280         if ( tcp->th_ack )
00281                 quirks |= QUIRK_ACK;
00282         if ( tcp->th_urp )
00283                 quirks |= QUIRK_URG;
00284         if ( tcp->th_x2 )
00285                 quirks |= QUIRK_X2;
00286 
00287         // Parse TCP options.
00288         u_char* options = (u_char*) tcp + sizeof(struct tcphdr);
00289         u_char* opt_end = (u_char*) tcp + tcp_hdr_len;
00290 
00291         while ( options < opt_end )
00292                 {
00293                 unsigned int opt = options[0];
00294 
00295                 if ( opt == TCPOPT_EOL )
00296                         {
00297                         op[optcount++] = TCPOPT_EOL;
00298                         if ( ++options < opt_end )
00299                                 quirks |= QUIRK_PAST;
00300 
00301                         // All done - could flag if more junk left over ....
00302                         break;
00303                         }
00304 
00305                 if ( opt == TCPOPT_NOP )
00306                         {
00307                         op[optcount++] = TCPOPT_NOP;
00308                         ++options;
00309                         continue;
00310                         }
00311 
00312                 if ( options + 1 >= opt_end )
00313                         {
00314                         // We've run off the end, no room for the length.
00315                         quirks |= QUIRK_BROKEN;
00316                         break;
00317                         }
00318 
00319                 unsigned int opt_len = options[1];
00320 
00321                 if ( options + opt_len > opt_end )
00322                         {
00323                         // No room for rest of the options.
00324                         quirks |= QUIRK_BROKEN;
00325                         break;
00326                         }
00327 
00328                 if ( opt_len == 0 )
00329                         // Trashed length field.
00330                         break;
00331 
00332                 switch ( opt ) {
00333                 case TCPOPT_SACK_PERMITTED:
00334                         // SACKOK LEN
00335                         op[optcount] = TCPOPT_SACK_PERMITTED;
00336                         break;
00337 
00338                 case TCPOPT_MAXSEG:
00339                         // MSS LEN D0 D1
00340                         if ( opt_len < 4 )
00341                                 break;  // bad length
00342 
00343                         op[optcount] = TCPOPT_MAXSEG;
00344                         MSS = (options[2] << 8) | options[3];
00345                         break;
00346 
00347                 case TCPOPT_WINDOW:
00348                         // WSCALE LEN D0
00349                         if ( opt_len < 3 )
00350                                 break;  // bad length
00351 
00352                         op[optcount] = TCPOPT_WINDOW;
00353                         winscale = options[2];
00354                         break;
00355 
00356                 case TCPOPT_TIMESTAMP:
00357                         // TSTAMP LEN T0 T1 T2 T3 A0 A1 A2 A3
00358                         if ( opt_len < 10 )
00359                                 break;  // bad length
00360 
00361                         op[optcount] = TCPOPT_TIMESTAMP;
00362 
00363                         tstamp = ntohl(extract_uint32(options + 2));
00364 
00365                         if ( extract_uint32(options + 6) )
00366                                 quirks |= QUIRK_T2;
00367                         break;
00368 
00369                 default:        // just skip over
00370                         op[optcount]=opt;
00371                         break;
00372                 }
00373 
00374                 if ( optcount < MAXOPT - 1 )
00375                         ++optcount;
00376                 else
00377                         quirks |= QUIRK_BROKEN;
00378 
00379                 options += opt_len;
00380                 }
00381 
00382         struct os_type os_from_print;
00383         int id = sessions->Get_OS_From_SYN(&os_from_print,
00384                         uint16(ip->TotalLen()),
00385                         uint8(ip->DF()), uint8(ip->TTL()),
00386                         uint16(ntohs(tcp->th_win)),
00387                         uint8(optcount), op,
00388                         uint16(MSS), uint8(winscale),
00389                         tstamp, quirks,
00390                         uint8(tcp->th_flags & (TH_ECE|TH_CWR)));
00391 
00392         if ( sessions->CompareWithPreviousOSMatch(ip->SrcAddr4(), id) )
00393                 {
00394                 RecordVal* os = new RecordVal(OS_version);
00395 
00396                 os->Assign(0, new StringVal(os_from_print.os));
00397 
00398                 if ( os_from_print.desc )
00399                         os->Assign(1, new StringVal(os_from_print.desc));
00400                 else
00401                         os->Assign(1, new StringVal(""));
00402 
00403                 os->Assign(2, new Val(os_from_print.dist, TYPE_COUNT));
00404                 os->Assign(3, new EnumVal(os_from_print.match, OS_version_inference));
00405 
00406                 return os;
00407                 }
00408 
00409         return 0;
00410         }
00411 
00412 int TCP_Connection::ParseTCPOptions(const struct tcphdr* tcp,
00413                                     proc_tcp_option_t proc,
00414                                     TCP_Connection* conn,
00415                                     int is_orig,
00416                                     void* cookie)
00417         {
00418         // Parse TCP options.
00419         const u_char* options = (const u_char*) tcp + sizeof(struct tcphdr);
00420         const u_char* opt_end = (const u_char*) tcp + tcp->th_off * 4;
00421 
00422         while ( options < opt_end )
00423                 {
00424                 unsigned int opt = options[0];
00425 
00426                 unsigned int opt_len;
00427 
00428                 if ( opt < 2 )
00429                         opt_len = 1;
00430 
00431                 else if ( options + 1 >= opt_end )
00432                         // We've run off the end, no room for the length.
00433                         return -1;
00434 
00435                 else
00436                         opt_len = options[1];
00437 
00438                 if ( opt_len == 0 )
00439                         return -1;      // trashed length field
00440 
00441                 if ( options + opt_len > opt_end )
00442                         // No room for rest of option.
00443                         return -1;
00444 
00445                 if ( (*proc)(opt, opt_len, options, conn, is_orig, cookie) == -1 )
00446                         return -1;
00447 
00448                 options += opt_len;
00449 
00450                 if ( opt == TCPOPT_EOL )
00451                         // All done - could flag if more junk left over ....
00452                         break;
00453                 }
00454 
00455         return 0;
00456         }
00457 
00458 int TCP_Connection::TCPOptionEvent(unsigned int opt,
00459                                    unsigned int optlen,
00460                                    const u_char* /* option */,
00461                                    TCP_Connection* conn,
00462                                    int is_orig,
00463                                    void* cookie)
00464         {
00465         if ( tcp_option )
00466                 {
00467                 val_list* vl = new val_list();
00468 
00469                 vl->append(conn->BuildConnVal());
00470                 vl->append(new Val(is_orig, TYPE_BOOL));
00471                 vl->append(new Val(opt, TYPE_COUNT));
00472                 vl->append(new Val(optlen, TYPE_COUNT));
00473 
00474                 conn->ConnectionEvent(tcp_option, vl);
00475                 }
00476 
00477         return 0;
00478         }
00479 
00480 void TCP_Connection::NextPacket(double t, int is_orig,
00481                         const IP_Hdr* ip,
00482                         int len, int caplen, const u_char*& data,
00483                         int& record_packet, int& record_content,
00484                         const struct pcap_pkthdr* pcap_hdr,
00485                         const u_char* const pcap_pkt,
00486                         int hdr_size)
00487         {
00488         // DEBUG_MSG("%.6f TCP_Connection::NextPacket\n", network_time);
00489 
00490         const struct tcphdr* tp = (const struct tcphdr*) data;
00491         uint32 tcp_hdr_len = tp->th_off * 4;
00492 
00493         if ( tcp_hdr_len < sizeof(struct tcphdr) )
00494                 {
00495                 Weird("bad_TCP_header_len");
00496                 return;
00497                 }
00498 
00499         if ( tcp_hdr_len > uint32(len) ||
00500              sizeof(struct tcphdr) > uint32(caplen) )
00501                 {
00502                 // This can happen even with the above test, due to TCP
00503                 // options.
00504                 Weird("truncated_header");
00505                 return;
00506                 }
00507 
00508         len -= tcp_hdr_len;     // remove TCP header
00509         caplen -= tcp_hdr_len;
00510         data += tcp_hdr_len;
00511 
00512         TCP_Endpoint* endpoint = is_orig ? orig : resp;
00513         TCP_Endpoint* peer = endpoint->peer;
00514 
00515         if ( ! ignore_checksums && caplen >= len &&
00516              ! endpoint->ValidChecksum(tp, len) )
00517                 {
00518                 Weird("bad_TCP_checksum");
00519                 return;
00520                 }
00521 
00522         if ( rule_matcher )
00523                 {
00524                 if ( is_orig && ! orig_match_state )
00525                         InitEndpointMatcher(ip, caplen, 1);
00526 
00527                 if ( ! is_orig && ! resp_match_state )
00528                         InitEndpointMatcher(ip, caplen, 0);
00529                 }
00530 
00531         u_char flags = tp->th_flags;
00532         uint32 base_seq = ntohl(tp->th_seq);
00533         uint32 ack_seq = ntohl(tp->th_ack);
00534         int SYN = flags & TH_SYN;
00535         int FIN = flags & TH_FIN;
00536         int RST = flags & TH_RST;
00537         int ACK = flags & TH_ACK;
00538         int seq_len = len;      // length in terms of sequence space
00539 
00540         // Note, the offered window on an initial SYN is unscaled, even
00541         // if the SYN includes scaling, so we need to do the following
00542         // test *before* updating the scaling information below.  (Hmmm,
00543         // how does this work for windows on SYN/ACKs? ###)
00544         int scale = endpoint->window_scale;
00545         unsigned int window = (ntohs(tp->th_win)) << scale;
00546 
00547         if ( ! SYN )
00548                 {
00549                 // Don't analyze window values off of SYNs, they're sometimes
00550                 // immediately rescinded.
00551 
00552                 // ### Decide whether to accept new window based on AM policy.
00553                 if ( int(base_seq - endpoint->window_seq) >= 0 &&
00554                      int(ack_seq - endpoint->window_ack_seq) >= 0 )
00555                         {
00556                         uint32 new_edge = ack_seq + window;
00557                         uint32 old_edge = endpoint->window_ack_seq + endpoint->window;
00558                         int advance = new_edge - old_edge;
00559 
00560                         if ( advance < 0 )
00561                                 {
00562                                 // A window recision.  We don't report these
00563                                 // for FINs or RSTs, or if the connection
00564                                 // has already been partially closed, since
00565                                 // such recisions occur frequently in practice,
00566                                 // probably as the receiver loses buffer memory
00567                                 // due to its process going away.
00568                                 //
00569                                 // We also, for window scaling, allow a bit
00570                                 // of slop ###.  This is because sometimes
00571                                 // there will be an apparent recision due
00572                                 // to the granularity of the scaling.
00573                                 if ( ! FIN && ! RST &&
00574                                      endpoint->state != TCP_CLOSED &&
00575                                      endpoint->state != TCP_RESET &&
00576                                      (-advance) >= (1 << scale) )
00577                                         Weird("window_recision");
00578                                 }
00579 
00580                         endpoint->window = window;
00581                         endpoint->window_ack_seq = ack_seq;
00582                         endpoint->window_seq = base_seq;
00583                         }
00584                 }
00585 
00586         if ( ! orig->did_close || ! resp->did_close )
00587                 last_time = t;
00588 
00589         if ( SYN )
00590                 {
00591                 ++seq_len;      // SYN consumes a byte of sequence space
00592                 if ( RST )
00593                         Weird("TCP_christmas");
00594 
00595                 if ( (flags & TH_URG) )
00596                         Weird("baroque_SYN");
00597 
00598                 if ( len > 0 )
00599                         // T/TCP definitely complicates this.
00600                         Weird("SYN_with_data");
00601 
00602                 RecordVal* SYN_vals =
00603                         BuildSYNPacketVal(is_orig, ip, tp)->AsRecordVal();
00604 
00605                 // ### In the following, we could be fooled by an
00606                 // inconsistent SYN retransmission.  Where's a normalizer
00607                 // when you need one?
00608 
00609                 // ### We know that field 5 is the window scaling ....
00610                 int scale = int(SYN_vals->Lookup(5)->CoerceToInt());
00611 
00612                 if ( scale < 0 )
00613                         { // no window scaling option
00614                         if ( ACK )
00615                                 { // window scaling not negotiated
00616                                 endpoint->window_scale = 0;
00617                                 peer->window_scale = 0;
00618                                 }
00619                         else
00620                                 // We're not offering window scaling.
00621                                 // Ideally, we'd remember this fact so that
00622                                 // if the SYN/ACK *does* include window
00623                                 // scaling, we know it won't be negotiated.
00624                                 // But it's a pain to track that, and hard
00625                                 // to see how an adversarial responder could
00626                                 // use it to evade.  Also, if we *do* want
00627                                 // to track it, we could do so using
00628                                 // connection_SYN_packet.
00629                                 endpoint->window_scale = 0;
00630                         }
00631                 else
00632                         {
00633                         endpoint->window_scale = scale;
00634                         endpoint->window_seq = base_seq;
00635                         endpoint->window_ack_seq = ack_seq;
00636 
00637                         peer->window_seq = ack_seq;
00638                         peer->window_ack_seq = base_seq;
00639                         }
00640 
00641                 if ( connection_SYN_packet )
00642                         {
00643                         val_list* vl = new val_list;
00644                         vl->append(BuildConnVal());
00645                         vl->append(SYN_vals);
00646                         ConnectionEvent(connection_SYN_packet, vl);
00647                         }
00648                 else
00649                         Unref(SYN_vals);
00650 
00651                 // Passive fingerprinting.
00652                 //
00653                 // is_orig will be removed once we can do SYN-ACK
00654                 // fingerprinting.
00655                 if ( OS_version_found && is_orig )
00656                         {
00657                         Val src_addr_val(*OrigAddr(), TYPE_ADDR);
00658                         if ( generate_OS_version_event->Size() == 0 ||
00659                              generate_OS_version_event->Lookup(&src_addr_val) )
00660                                 {
00661                                 RecordVal* OS_val =
00662                                         BuildOSVal(is_orig, ip, tp, tcp_hdr_len);
00663                                 if ( OS_val )
00664                                         { // found new OS version
00665                                         val_list* vl = new val_list;
00666                                         vl->append(BuildConnVal());
00667                                         vl->append(new AddrVal(OrigAddr()));
00668                                         vl->append(OS_val);
00669                                         ConnectionEvent(OS_version_found, vl);
00670                                         }
00671                                 }
00672                         }
00673                 }
00674 
00675         if ( FIN )
00676                 {
00677                 ++seq_len;      // FIN consumes a byte of sequence space
00678                 // Remember the relative seq in FIN_seq.
00679                 endpoint->FIN_seq = base_seq - endpoint->StartSeq() + seq_len;
00680 
00681                 if ( t < endpoint->last_time + tcp_storm_interarrival_thresh &&
00682                      ++endpoint->FIN_cnt == tcp_storm_thresh )
00683                         Weird("FIN_storm");
00684 
00685                 else if ( endpoint->FIN_cnt == 0 )
00686                         // Remember that we've seen a FIN.
00687                         ++endpoint->FIN_cnt;
00688                 }
00689 
00690         if ( RST )
00691                 {
00692                 if ( t < endpoint->last_time + tcp_storm_interarrival_thresh &&
00693                      ++endpoint->RST_cnt == tcp_storm_thresh )
00694                         Weird("RST_storm");
00695 
00696                 else if ( endpoint->RST_cnt == 0 )
00697                         ++endpoint->RST_cnt;    // Remember we've seen a RST
00698 
00699 #ifdef ACTIVE_MAPPING
00700 //              if ( peer->state == TCP_INACTIVE )
00701 //                  debug_msg("rst while inactive\n"); // ### Cold-start: what to do?
00702 //              else
00703 
00704                 const NumericData* AM_policy;
00705                 get_map_result(ip->DstAddr4(), AM_policy);
00706 
00707                 if ( base_seq == endpoint->ack_seq )
00708                         ;        // everyone should accept a RST in sequence
00709 
00710                 else if ( endpoint->window == 0 )
00711                         ; // ### Cold Start: we don't know the window,
00712                           // so just go along for now
00713 
00714                 else
00715                         {
00716                         uint32 right_edge = endpoint->ack_seq +
00717                                 (endpoint->window << endpoint->window_scale);
00718 
00719                         if ( base_seq < right_edge  )
00720                                 {
00721                                 if ( ! AM_policy->accepts_rst_in_window )
00722                                         {
00723 #if 0
00724                                         debug_msg("Machine does not accept RST merely in window; ignoring. t=%.6f,base=%u, ackseq=%u, window=%hd \n",
00725                                                 network_time, base_seq, endpoint->ack_seq, window);
00726 #endif
00727                                         return;
00728                                         }
00729                                 }
00730 
00731                         else if ( ! AM_policy->accepts_rst_outside_window )
00732                                 {
00733 #if 0
00734                                 debug_msg("Machine does not accept RST outside window; ignoring. t=%.6f,base=%u, ackseq=%u, window=%hd \n",
00735                                         network_time, base_seq, endpoint->ack_seq, window);
00736 #endif
00737                                 return;
00738                                 }
00739                         }
00740 #endif
00741 
00742                 if ( len > 0 )
00743                         {
00744                         // This now happens often enough that it's
00745                         // not in the least interesting.
00746                         // Weird("RST_with_data");
00747 
00748                         // Don't include the data in the computation of
00749                         // the sequence space for this connection, as
00750                         // it's not in fact part of the TCP stream.
00751                         seq_len = 0;
00752                         }
00753 
00754                 PacketWithRST();
00755                 }
00756 
00757         if ( ACK && is_orig && ! seen_first_ACK &&
00758              (endpoint->state == TCP_ESTABLISHED || endpoint->state == TCP_SYN_SENT) )
00759                 {
00760                 seen_first_ACK = 1;
00761                 Event(connection_first_ACK);
00762                 }
00763 
00764         uint32 last_seq = base_seq + seq_len;
00765 
00766         if ( endpoint->state == TCP_INACTIVE )
00767                 {
00768                 if ( ! SYN )
00769                         {
00770                         // This is a partial connection - set up the
00771                         // initial sequence numbers as though we saw
00772                         // a SYN, to keep the relative byte numbering
00773                         // consistent.
00774                         // ## endpoint->ack_seq = endpoint->start_seq = base_seq - 1;
00775                         endpoint->InitAckSeq(base_seq - 1);
00776                         endpoint->InitStartSeq(base_seq - 1);
00777                         }
00778                 else
00779                         {
00780                         // ## endpoint->ack_seq = endpoint->start_seq = base_seq;
00781                         endpoint->InitAckSeq(base_seq);
00782                         endpoint->InitStartSeq(base_seq);
00783                         }
00784 
00785                 // ## endpoint->last_seq = last_seq;
00786                 endpoint->InitLastSeq(last_seq);
00787                 endpoint->start_time = t;
00788                 }
00789 
00790         int delta_last = seq_delta(last_seq, endpoint->LastSeq());
00791 
00792         if ( (SYN || RST) && (delta_last > TOO_LARGE_SEQ_DELTA || delta_last < -TOO_LARGE_SEQ_DELTA) )
00793                 // ### perhaps trust RST seq #'s if initial and not too
00794                 // outlandish, but not if they're coming after the other
00795                 // side has sent a FIN - trust the FIN ack instead
00796                 ;
00797 
00798         else if ( FIN && endpoint->LastSeq() == endpoint->StartSeq() + 1 )
00799                 // Update last_seq based on the FIN even if delta_last < 0.
00800                 // This is to accommodate > 2 GB connections for which
00801                 // we've only seen the SYN and the FIN (hence the check
00802                 // for last_seq == start_seq + 1).
00803                 endpoint->UpdateLastSeq(last_seq);
00804 
00805         else if ( endpoint->state == TCP_RESET )
00806                 // don't trust any subsequent sequence numbers
00807                 ;
00808 
00809         else if ( delta_last > 0 )
00810                 // ### check for large jumps here.
00811                 // ## endpoint->last_seq = last_seq;
00812                 endpoint->UpdateLastSeq(last_seq);
00813 
00814         else if ( delta_last <= 0 )
00815                 // ### ++retransmit, unless this is a pure ack
00816                 ;
00817 
00818         if ( ACK )
00819                 {
00820                 if ( peer->state == TCP_INACTIVE )
00821                         {
00822                         if ( ! SYN && ! FIN && ! RST )
00823                                 {
00824                                 if ( endpoint->state == TCP_SYN_SENT ||
00825                                      endpoint->state == TCP_SYN_ACK_SENT ||
00826                                      endpoint->state == TCP_ESTABLISHED )
00827                                         {
00828                                         // We've already sent a SYN, but
00829                                         // that hasn't roused the other
00830                                         // end, yet we're ack'ing their
00831                                         // data.
00832                                         if ( weird == 0 )
00833                                                 Weird("possible_split_routing");
00834                                         }
00835                                 }
00836 
00837                         // Start the sequence numbering as if there
00838                         // was an initial SYN, so the relative
00839                         // numbering of subsequent data packets stays
00840                         // consistent.
00841                         // ## peer->start_seq = peer->ack_seq = peer->last_seq =
00842                         // ##   ack_seq - 1;
00843                         peer->InitStartSeq(ack_seq - 1);
00844                         peer->InitAckSeq(ack_seq - 1);
00845                         peer->InitLastSeq(ack_seq - 1);
00846                         }
00847 
00848                 else if ( ! RST )
00849                         { // don't trust ack's in RST packets
00850                         int delta_ack = seq_delta(ack_seq, peer->AckSeq());
00851                         if ( ack_seq == 0 && delta_ack > TOO_LARGE_SEQ_DELTA )
00852                                 // More likely that this is a broken ack
00853                                 // than a large connection that happens
00854                                 // to land on 0 in the sequence space.
00855                                 ;
00856 
00857                         else if ( delta_ack > 0 )
00858                                 peer->UpdateAckSeq(ack_seq);
00859                         }
00860 
00861                 peer->AckReceived(ack_seq - peer->StartSeq());
00862                 }
00863 
00864         endpoint->last_time = t;
00865 
00866         int do_close = 0;       // whether to report the connection as closed
00867         int gen_event = 0;      // if so, whether to generate an event
00868 
00869         switch ( endpoint->state ) {
00870 
00871         case TCP_INACTIVE:
00872                 {
00873                 if ( SYN )
00874                         {
00875                         if ( is_orig )
00876                                 {
00877                                 if ( ACK )
00878                                         {
00879                                         Weird("connection_originator_SYN_ack");
00880                                         endpoint->SetState(TCP_SYN_ACK_SENT);
00881                                         }
00882                                 else
00883                                         endpoint->SetState(TCP_SYN_SENT);
00884 
00885                                 if ( connection_attempt )
00886                                         ADD_TIMER(&TCP_Connection::AttemptTimer,
00887                                                 t + tcp_attempt_delay, 1,
00888                                                 TIMER_TCP_ATTEMPT);
00889                                 }
00890                         else
00891                                 {
00892                                 if ( ACK )
00893                                         {
00894                                         if ( peer->state != TCP_INACTIVE &&
00895                                              peer->state != TCP_PARTIAL &&
00896                                              ! seq_between(ack_seq, peer->StartSeq(), peer->LastSeq()) )
00897                                                 Weird("bad_SYN_ack");
00898                                         }
00899 
00900                                 else if ( peer->state == TCP_SYN_ACK_SENT &&
00901                                           base_seq == endpoint->StartSeq() )
00902                                         {
00903                                         // This is a SYN/SYN-ACK reversal,
00904                                         // per the discussion in IsReuse.
00905                                         // Flip the endpoints and establish
00906                                         // the connection.
00907 
00908                                         // Flip state statistics so that the
00909                                         // later SetState works as it should.
00910                                         sessions->tcp_stats.FlipState(orig->state, resp->state);
00911                                         TCP_Endpoint* tmp_ep = resp;
00912                                         resp = orig;
00913                                         orig = tmp_ep;
00914 
00915                                         uint32 tmp_addr[NUM_ADDR_WORDS];
00916                                         copy_addr(resp_addr, tmp_addr);
00917                                         copy_addr(orig_addr, resp_addr);
00918                                         copy_addr(tmp_addr, orig_addr);
00919 
00920                                         uint16 tmp_port = resp_port;
00921                                         resp_port = orig_port;
00922                                         orig_port = tmp_port;
00923 
00924                                         Unref(conn_val);
00925                                         conn_val = 0;
00926 
00927                                         RuleEndpointState* tmp = orig_match_state;
00928                                         orig_match_state = resp_match_state;
00929                                         resp_match_state = tmp;
00930                                         if ( orig_match_state )
00931                                                 orig_match_state->FlipIsOrig();
00932                                         if ( resp_match_state )
00933                                                 resp_match_state->FlipIsOrig();
00934 
00935                                         peer->SetState(TCP_ESTABLISHED);
00936                                         }
00937 
00938                                 else
00939                                         Weird("simultaneous_open");
00940 
00941                                 if ( peer->state == TCP_SYN_SENT )
00942                                         peer->SetState(TCP_ESTABLISHED);
00943                                 else if ( peer->state == TCP_INACTIVE )
00944                                         {
00945                                         // If we were to ignore SYNs and
00946                                         // only instantiate state on SYN
00947                                         // acks, then we'd do:
00948                                         //    peer->SetState(TCP_ESTABLISHED);
00949                                         // here.
00950                                         Weird("unsolicited_SYN_response");
00951                                         }
00952 
00953                                 endpoint->SetState(TCP_ESTABLISHED);
00954 
00955                                 if ( peer->state != TCP_PARTIAL )
00956                                         {
00957                                         Event(connection_established);
00958                                         EnableStatusUpdateTimer();
00959                                         }
00960                                 }
00961                         }
00962 
00963                 if ( FIN )
00964                         {
00965                         endpoint->SetState(TCP_CLOSED);
00966                         do_close = gen_event = 1;
00967                         if ( peer->state != TCP_PARTIAL && ! SYN )
00968                                 Weird("spontaneous_FIN");
00969                         }
00970 
00971                 if ( RST )
00972                         {
00973                         endpoint->SetState(TCP_RESET);
00974 
00975                         int is_reject = 0;
00976 
00977                         if ( is_orig )
00978                                 {
00979                                 // If our peer is established then we saw
00980                                 // a SYN-ack but not SYN - so a reverse
00981                                 // scan, and we should treat this as a
00982                                 // reject.
00983                                 if ( peer->state == TCP_ESTABLISHED )
00984                                         is_reject = 1;
00985                                 }
00986 
00987                         else if ( peer->state == TCP_SYN_SENT ||
00988                                   peer->state == TCP_SYN_ACK_SENT )
00989                                 // We're rejecting an initial SYN.
00990                                 is_reject = 1;
00991 
00992                         do_close = 1;
00993                         gen_event = ! is_reject;
00994 
00995                         if ( is_reject )
00996                                 Event(connection_rejected);
00997 
00998                         else if ( peer->state == TCP_INACTIVE )
00999                                 Weird("spontaneous_RST");
01000                         }
01001 
01002                 if ( endpoint->state == TCP_INACTIVE )
01003                         { // No control flags to change the state.
01004                         if ( ! is_orig && len == 0 &&
01005                              orig->state == TCP_SYN_SENT )
01006                                 // Some eccentric TCP's will ack an initial
01007                                 // SYN prior to sending a SYN reply (hello,
01008                                 // ftp.microsoft.com).  For those, don't
01009                                 // consider the ack as forming a partial
01010                                 // connection.
01011                                 ;
01012                         else
01013                                 {
01014                                 endpoint->SetState(TCP_PARTIAL);
01015                                 EnableStatusUpdateTimer();
01016                                 
01017                                 if ( peer->state == TCP_PARTIAL )
01018                                         // We've seen both sides of a partial
01019                                         // connection, report it.
01020                                         Event(partial_connection);
01021                                 }
01022                         }
01023                 }
01024                 break;
01025 
01026         case TCP_SYN_SENT:
01027         case TCP_SYN_ACK_SENT:
01028                 {
01029                 if ( SYN )
01030                         {
01031                         if ( is_orig )
01032                                 {
01033                                 if ( ACK && ! FIN && ! RST &&
01034                                      endpoint->state != TCP_SYN_ACK_SENT )
01035                                         Weird("repeated_SYN_with_ack");
01036                                 else if ( peer->state == TCP_INACTIVE )
01037                                         // ###
01038                                         start_time = endpoint->start_time = t;
01039                                 }
01040                         else
01041                                 {
01042                                 if ( ! ACK &&
01043                                      endpoint->state != TCP_SYN_SENT )
01044                                         Weird("repeated_SYN_reply_wo_ack");
01045                                 }
01046 
01047                         if ( base_seq != endpoint->StartSeq() )
01048                                 {
01049                                 Weird("SYN_seq_jump");
01050                                 // ## endpoint->ack_seq = endpoint->start_seq = base_seq;
01051                                 // ## endpoint->last_seq = last_seq;
01052                                 endpoint->InitStartSeq(base_seq);
01053                                 endpoint->InitAckSeq(base_seq);
01054                                 endpoint->InitLastSeq(last_seq);
01055                                 }
01056                         }
01057 
01058                 if ( FIN )
01059                         {
01060                         if ( peer->state == TCP_INACTIVE ||
01061                              peer->state == TCP_SYN_SENT )
01062                                 Weird("inappropriate_FIN");
01063                         endpoint->SetState(TCP_CLOSED);
01064                         do_close = gen_event = 1;
01065                         }
01066 
01067                 if ( RST )
01068                         {
01069                         endpoint->SetState(TCP_RESET);
01070                         ConnectionReset();
01071                         do_close = 1;
01072                         }
01073                 else if ( len > 0 )
01074                         Weird("data_before_established");
01075                 }
01076                 break;
01077 
01078         case TCP_ESTABLISHED:
01079         case TCP_PARTIAL:
01080                 {
01081                 if ( SYN )
01082                         {
01083                         if ( endpoint->state == TCP_PARTIAL &&
01084                              peer->state == TCP_INACTIVE && ! ACK )
01085                                 {
01086                                 Weird("SYN_after_partial");
01087                                 endpoint->SetState(TCP_SYN_SENT);
01088                                 }
01089 
01090                         if ( endpoint->Size() > 0 )
01091                                 Weird("SYN_inside_connection");
01092 
01093                         if ( is_orig && peer->state == TCP_ESTABLISHED ) // ###
01094                                 start_time = endpoint->start_time = t;
01095 
01096                         if ( base_seq != endpoint->StartSeq() )
01097                                 Weird("SYN_seq_jump");
01098 
01099                         // Make a guess that somehow the connection didn't
01100                         // get established, and this SYN will be the
01101                         // one that actually sets it up.
01102                         // ## endpoint->ack_seq = endpoint->start_seq = base_seq;
01103                         // ## endpoint->last_seq = last_seq;
01104                         endpoint->InitStartSeq(base_seq);
01105                         endpoint->InitAckSeq(base_seq);
01106                         endpoint->InitLastSeq(last_seq);
01107                         }
01108 
01109                 if ( FIN && ! RST )     // ###
01110                         { // should check sequence/ack numbers here ###
01111                         endpoint->SetState(TCP_CLOSED);
01112 
01113                         if ( peer->state == TCP_RESET &&
01114                              peer->prev_state == TCP_CLOSED )
01115                                 // The peer sent a FIN followed by a RST.
01116                                 // Turn it back into CLOSED state, because
01117                                 // this was actually normal termination.
01118                                 peer->SetState(TCP_CLOSED);
01119 
01120                         do_close = gen_event = 1;
01121                         }
01122 
01123                 if ( RST )
01124                         {
01125                         endpoint->SetState(TCP_RESET);
01126                         do_close = 1;
01127 
01128                         if ( peer->state != TCP_RESET ||
01129                              peer->prev_state != TCP_ESTABLISHED )
01130                                 ConnectionReset();
01131                         }
01132                 }
01133                 break;
01134 
01135         case TCP_CLOSED:
01136                 {
01137                 if ( SYN )
01138                         Weird("SYN_after_close");
01139 
01140                 if ( FIN && delta_last > 0 )
01141                         // Probably should also complain on FIN recision.
01142                         // That requires an extra state variable to avoid
01143                         // generating slews of weird's when a TCP gets
01144                         // seriously confused (this from experience).
01145                         Weird("FIN_advanced_last_seq");
01146 
01147                 if ( RST )
01148                         {
01149                         endpoint->SetState(TCP_RESET);
01150 
01151                         if ( ! endpoint->did_close )
01152                                 // RST after FIN.
01153                                 do_close = 1;
01154 
01155                         if ( connection_reset )
01156                                 ADD_TIMER(&TCP_Connection::ResetTimer,
01157                                                 t + tcp_reset_delay, 1,
01158                                                 TIMER_TCP_RESET);
01159                         }
01160                 }
01161                 break;
01162 
01163         case TCP_RESET:
01164                 {
01165                 if ( SYN )
01166                         Weird("SYN_after_reset");
01167                 if ( FIN )
01168                         Weird("FIN_after_reset");
01169 
01170                 if ( len > 0 && ! RST )
01171                         Weird("data_after_reset");
01172                 }
01173                 break;
01174         }
01175 
01176         if ( tcp_packet )
01177                 {
01178                 char tcp_flags[256];
01179                 int tcp_flag_len = 0;
01180 
01181                 if ( SYN ) tcp_flags[tcp_flag_len++] = 'S';
01182                 if ( FIN ) tcp_flags[tcp_flag_len++] = 'F';
01183                 if ( RST ) tcp_flags[tcp_flag_len++] = 'R';
01184                 if ( ACK ) tcp_flags[tcp_flag_len++] = 'A';
01185                 if ( flags & TH_PUSH ) tcp_flags[tcp_flag_len++] = 'P';
01186                 if ( flags & TH_URG ) tcp_flags[tcp_flag_len++] = 'U';
01187 
01188                 tcp_flags[tcp_flag_len] = '\0';
01189 
01190                 val_list* vl = new val_list();
01191 
01192                 vl->append(BuildConnVal());
01193                 vl->append(new Val(is_orig, TYPE_BOOL));
01194                 vl->append(new StringVal(tcp_flags));
01195                 vl->append(new Val(base_seq - endpoint->StartSeq(), TYPE_COUNT));
01196                 vl->append(new Val(ACK ? ack_seq - peer->StartSeq() : 0, TYPE_COUNT));
01197                 vl->append(new Val(len, TYPE_COUNT));
01198                 vl->append(new StringVal(caplen, (const char*) data));
01199 
01200                 ConnectionEvent(tcp_packet, vl);
01201                 }
01202 
01203         if ( tcp_option && tcp_hdr_len > sizeof(*tp) &&
01204              tcp_hdr_len <= uint32(caplen) )
01205                 ParseTCPOptions(tp, TCPOptionEvent, this, is_orig, 0);
01206 
01207         if ( trace_rewriter && pcap_hdr )
01208                 trace_rewriter->NextPacket(is_orig, t, pcap_hdr,
01209                                         pcap_pkt, hdr_size, ip->IP4_Hdr(), tp);
01210 
01211         if ( src_pkt_writer && pcap_hdr )
01212                 src_pkt_writer->NextPacket(pcap_hdr, pcap_pkt);
01213 
01214         int need_contents = 0;
01215         if ( len > 0 && (caplen >= len || endpoint->Analyzer()) &&
01216              ! RST && ! skip )
01217                 {
01218                 int data_seq = base_seq - endpoint->StartSeq();
01219                 if ( SYN )
01220                         ++data_seq;     // skip over SYN octet
01221 
01222                 need_contents = endpoint->DataSent(t, data_seq,
01223                                                 len, caplen, data, ip, tp);
01224                 }
01225 
01226         endpoint->CheckEOF();
01227 
01228         if ( do_close )
01229                 {
01230                 // We need to postpone doing this until after we process
01231                 // DataSent, so we don't generate a connection_finished event
01232                 // until after data perhaps included with the FIN is processed.
01233                 ConnectionClosed(endpoint, peer, gen_event);
01234                 }
01235 
01236         record_content = need_contents || RecordContents();
01237 //###   record_content = RecordContents();      // a hack to avoid dumping EVERY packet
01238         record_packet = record_packets || SYN || FIN || RST;
01239         }
01240 
01241 void TCP_Connection::Deliver(TCP_Endpoint* /* sender */,
01242                         int /* seq */, int /* len */,
01243                         const u_char* /* data */)
01244         {
01245         }
01246 
01247 void TCP_Connection::Undelivered(TCP_Endpoint* sender, int seq, int len)
01248         {
01249         // This can happen because we're processing a trace that's been
01250         // filtered.  For example, if it's just SYN/FIN data, then there
01251         // can be data in the FIN packet, but it's undelievered because
01252         // it's out of sequence.
01253         if ( content_gap )
01254                 {
01255                 val_list* vl = new val_list;
01256                 vl->append(BuildConnVal());
01257                 vl->append(new Val(IsOrig(sender), TYPE_BOOL));
01258                 vl->append(new Val(seq, TYPE_COUNT));
01259                 vl->append(new Val(len, TYPE_COUNT));
01260 
01261                 ConnectionEvent(content_gap, vl);
01262                 }
01263 
01264         if ( trace_rewriter )
01265                 trace_rewriter->ContentGap(IsOrig(sender), len);
01266         }
01267 
01268 void TCP_Connection::NewLine(TCP_ContentLine* /* sender */, int /* length */, const char* /* line */)
01269         {
01270         }
01271 
01272 void TCP_Connection::SetEnv(int /* is_orig */, char* name, char* val)
01273         {
01274         delete [] name;
01275         delete [] val;
01276         }
01277 
01278 void TCP_Connection::AttemptTimer(double /* t */)
01279         {
01280         if ( ! is_active )
01281                 return;
01282 
01283         if ( (orig->state == TCP_SYN_SENT || orig->state == TCP_SYN_ACK_SENT) &&
01284              resp->state == TCP_INACTIVE )
01285                 {
01286                 Event(connection_attempt);
01287                 is_active = 0;
01288 
01289                 // All done with this connection.
01290                 sessions->Remove(this);
01291                 }
01292         }
01293 
01294 void TCP_Connection::PartialCloseTimer(double /* t */)
01295         {
01296         if ( ! is_active )
01297                 return;
01298 
01299         if ( orig->state != TCP_INACTIVE && resp->state != TCP_INACTIVE &&
01300              (! orig->did_close || ! resp->did_close) )
01301                 {
01302                 if ( orig->state == TCP_RESET || resp->state == TCP_RESET )
01303                         // Presumably the RST is what caused the partial
01304                         // close.  Don't report it.
01305                         return;
01306 
01307                 Event(connection_partial_close);
01308                 sessions->Remove(this);
01309                 }
01310         }
01311 
01312 void TCP_Connection::ExpireTimer(double t)
01313         {
01314         if ( ! is_active )
01315                 return;
01316 
01317         if ( last_time + tcp_connection_linger < t )
01318                 {
01319                 if ( orig->did_close || resp->did_close )
01320                         {
01321                         // No activity for tcp_connection_linger seconds, and
01322                         // at least one side has closed.  See whether
01323                         // connection has likely terminated.
01324                         if ( (orig->did_close && resp->did_close) ||
01325                              (orig->state == TCP_RESET ||
01326                               resp->state == TCP_RESET) ||
01327                              (orig->state == TCP_INACTIVE ||
01328                               resp->state == TCP_INACTIVE) )
01329                                 {
01330                                 // Either both closed, or one RST,
01331                                 // or half-closed.
01332 
01333                                 // The Timer has Ref()'d us and won't Unref()
01334                                 // us until we return, so it's safe to have
01335                                 // the session remove and Unref() us here.
01336                                 Event(connection_timeout);
01337                                 is_active = 0;
01338                                 sessions->Remove(this);
01339                                 return;
01340                                 }
01341                         }
01342 
01343                 if ( resp->state == TCP_INACTIVE )
01344                         {
01345                         if ( (orig->state == TCP_SYN_SENT ||
01346                               orig->state == TCP_SYN_ACK_SENT) )
01347                                 {
01348                                 if ( ! connection_attempt )
01349                                         {
01350                                         // Time out the connection attempt,
01351                                         // since the AttemptTimer isn't going
01352                                         // to do it for us, and we don't want
01353                                         // to clog the data structures with
01354                                         // old, failed attempts.
01355                                         Event(connection_timeout);
01356                                         is_active = 0;
01357                                         sessions->Remove(this);
01358                                         return;
01359                                         }
01360                                 }
01361 
01362                         else if ( orig->state == TCP_INACTIVE )
01363                                 {
01364                                 // Nothing ever happened on this connection.
01365                                 // This can occur when we see a trashed
01366                                 // packet - it's discarded by NextPacket
01367                                 // before setting up an attempt timer,
01368                                 // so we need to clean it up here.
01369                                 Event(connection_timeout);
01370                                 sessions->Remove(this);
01371                                 return;
01372                                 }
01373                         }
01374                 }
01375 
01376         // Connection still active, so reschedule timer.
01377         // ### if PQ_Element's were BroObj's, could just Ref the timer
01378         // and adjust its value here, instead of creating a new timer.
01379         ADD_TIMER(&TCP_Connection::ExpireTimer, t + tcp_session_timer,
01380                         0, TIMER_TCP_EXPIRE);
01381         }
01382 
01383 void TCP_Connection::ResetTimer(double /* t */)
01384         {
01385         if ( ! is_active )
01386                 return;
01387 
01388         if ( ! BothClosed() )
01389                 ConnectionReset();
01390 
01391         sessions->Remove(this);
01392         }
01393 
01394 void TCP_Connection::DeleteTimer(double /* t */)
01395         {
01396         sessions->Remove(this);
01397         }
01398 
01399 
01400 // The following need to be consistent with bro.init.
01401 #define CONTENTS_NONE 0
01402 #define CONTENTS_ORIG 1
01403 #define CONTENTS_RESP 2
01404 #define CONTENTS_BOTH 3
01405 
01406 void TCP_Connection::SetContentsFile(unsigned int direction, BroFile* f)
01407         {
01408         if ( direction == CONTENTS_NONE )
01409                 {
01410                 orig