http_connect.c File Reference

#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#include <sys/time.h>

Include dependency graph for http_connect.c:

Go to the source code of this file.

Defines

#define max(a, b)   ((a) >= (b) ? (a) : (b))
#define min(a, b)   ((a) <= (b) ? (a) : (b))

Enumerations

enum  inputs {
  SYN, FIN, RST, ACK_ONLY,
  DATA_ACK
}
enum  states {
  PENDING, SYN_SENT, FIN_SENT, RESET,
  IN_REQUEST, IN_RESPONSE
}

Functions

void begin_REQ (void)
void begin_RSP (void)
int check_ACK_advance (unsigned long old_ack)
void check_tuple_reuse (void)
long elapsed_ms (char *end, char *start)
void error_line (char *s)
void error_state (char *s)
void get_host_port (char *adr, char *host, char *port)
int get_sequence (char *p, unsigned long *begin, unsigned long *end, unsigned long *bytes)
void init_active (void)
void init_connection (void)
void log_ACT (char *how)
void log_connection (void)
void log_END (char *how)
void log_log (void)
void log_nosyn (void)
void log_REQ (void)
void log_RSP (void)
void log_SYN (void)
void main (int argc, char *argv[])
void more_REQ (void)
void more_RSP (void)
int parse_dump_record (void)
static void tvsub (struct timeval *tdiff, struct timeval *t1, struct timeval *t0)
void Usage (char *s)

Variables

int act_req_count = 0
int act_rsp_count = 0
unsigned long begin_seq
enum states connection_state = PENDING
char current_dst [25] = ""
unsigned long current_request_end
unsigned long current_response_end
char current_src [25] = ""
unsigned long current_synseq
char dh [25]
char dst_host [25]
char dst_port [10]
FILE * dumpFP
long elapsed
unsigned long end_seq
int err_count = 0
int fin_count = 0
char FIN_sent_time [20]
char fl [5]
char gt [3]
int has_ack
int has_seq
int have_ACK_error = 0
int have_FINdata_error = 0
int have_pending_acks = 0
int have_pending_fins = 0
int have_pending_othr = 0
int have_pending_rsts = 0
int have_value_error = 0
char input_name [256] = ""
enum inputs input_type
char last_connection_time [20]
unsigned long last_request_end
unsigned long last_response_end
enum states last_state = PENDING
timeval lastTime = {0,0}
char log_name [256] = ""
FILE * logFP
char lt [3]
unsigned long new_ack
int new_address = 0
char new_line [500]
FILE * outFP
char output_name [256] = ""
char p1 [50]
char p2 [50]
char p3 [50]
int pending_ack_count = 0
int pending_cmb_count = 0
int pending_fin_count = 0
int pending_oth_count = 0
int pending_rst_count = 0
int rc = 0
timeval recvTime
int report_ACK_err = 1
int req_count = 0
char request_end_time [20]
char response_end_time [20]
int rsp_count = 0
int rst_count = 0
char RST_sent_time [20]
unsigned long seq_bytes
char sh [25]
char src_host [25]
char src_port [10]
char start_request_time [20]
char start_response_time [20]
int syn_count = 0
int trm_count = 0
char ts [20]


Define Documentation

#define max a,
b   )     ((a) >= (b) ? (a) : (b))
 

Definition at line 74 of file http_connect.c.

#define min a,
b   )     ((a) <= (b) ? (a) : (b))
 

Definition at line 73 of file http_connect.c.


Enumeration Type Documentation

enum inputs
 

Enumerator:
SYN 
FIN 
RST 
ACK_ONLY 
DATA_ACK 

Definition at line 172 of file http_connect.c.

00172 {SYN, FIN, RST, ACK_ONLY, DATA_ACK};

enum states
 

Enumerator:
PENDING 
SYN_SENT 
FIN_SENT 
RESET 
IN_REQUEST 
IN_RESPONSE 

Definition at line 167 of file http_connect.c.


Function Documentation

void begin_REQ void   ) 
 

Definition at line 1272 of file http_connect.c.

References connection_state, current_request_end, IN_REQUEST, last_state, new_ack, request_end_time, start_request_time, and ts.

Referenced by main().

01273 {
01274  current_request_end = new_ack;
01275 
01276  /* record the request start time as beginning at the 
01277     tcpdump time stamp on this record */
01278 
01279  strcpy(start_request_time, ts);
01280  strcpy(request_end_time, ts);
01281 
01282  last_state = connection_state;
01283  connection_state = IN_REQUEST;
01284 }

void begin_RSP void   ) 
 

Definition at line 1296 of file http_connect.c.

References connection_state, current_response_end, end_seq, IN_RESPONSE, last_state, response_end_time, start_response_time, and ts.

Referenced by main().

01297 {
01298  current_response_end = end_seq;
01299 
01300  /* record timestamp of tcpdump record as current
01301  value of both start and end times of response
01302  (in case no later end time is found) */
01303 
01304  strcpy(start_response_time, ts); 
01305  strcpy(response_end_time, ts);
01306 
01307  last_state = connection_state;
01308  connection_state = IN_RESPONSE;
01309 }

int check_ACK_advance unsigned long  old_ack  ) 
 

Definition at line 1181 of file http_connect.c.

References error_state(), have_ACK_error, new_ack, and report_ACK_err.

Referenced by main().

01182 {
01183  
01184  if ((new_ack < old_ack) &&
01185       report_ACK_err)
01186     {
01187      if (have_ACK_error == 0)
01188         {
01189          error_state("ACK error -- backward");
01190          have_ACK_error = 1;
01191         }
01192      return(-1);
01193     }
01194  else
01195     return (0);
01196 }

Here is the call graph for this function:

void check_tuple_reuse void   ) 
 

Definition at line 1200 of file http_connect.c.

References begin_seq, connection_state, current_synseq, elapsed, elapsed_ms(), error_state(), FIN_SENT, has_seq, IN_REQUEST, IN_RESPONSE, init_connection(), last_connection_time, last_state, log_END(), log_REQ(), log_RSP(), RESET, SYN_SENT, and ts.

Referenced by main().

01201 {
01202  /* ignore duplicate SYNs (have same SYN sequence number) */
01203 
01204  if ((has_seq == 1) &&
01205      (current_synseq != begin_seq))
01206     {
01207       /* if a non-duplicate SYN comes before any other activity,
01208          treat it as terminating the incomplete connection and starting
01209          another */
01210      
01211      if ((connection_state == SYN_SENT) ||
01212          ((connection_state == RESET) && (last_state == SYN_SENT)))
01213         {
01214          log_END("TRM");
01215          init_connection();
01216          return;
01217         }
01218 
01219 
01220     /* It is quite possible to have a valid new
01221     connection that reuses the same source and destination
01222     IP.port address 4-tuple.  Treat this as valid if 
01223     there has been a FIN from the server or at least
01224     2*MSL has passed since seeing any previous packet
01225     from this connection (in case we missed the FIN).  If there
01226     was a FIN from the server, allow for the case it was an
01227     active close by the server (normal for HTTP 1.0), the 
01228     stack is a BSD derivative, and SO_REUSEADDR is is use
01229     (see Stevens vol. 1, pp 245) */ 
01230 
01231      if (connection_state == FIN_SENT)
01232         elapsed = 60001;  /* force beyond 2MSL test */
01233      else        
01234         elapsed = elapsed_ms(ts, last_connection_time);
01235 
01236      if (elapsed < 60000)  /* MSL of 30 seconds, minimum */
01237         error_state("Non-duplicate SYN in connection");
01238      else
01239     {
01240      /* perform all actions associated with the end of
01241             one connection and the beginning of the next 
01242             (see state PENDING) */
01243          switch (connection_state)
01244         {
01245         case FIN_SENT:
01246                  log_END("FIN");
01247                  break;
01248             case RESET:
01249                  if (last_state == IN_RESPONSE)
01250                     log_RSP();
01251 
01252                  log_END("RST");
01253                  break;
01254             case IN_RESPONSE:
01255                  log_RSP();
01256                  log_END("TRM");
01257                  break;
01258             case IN_REQUEST:
01259                  log_REQ();
01260                  log_END("TRM");
01261                  break;
01262             default:
01263                  break;
01264         }
01265          init_connection();
01266         }
01267     }
01268 }

Here is the call graph for this function:

long elapsed_ms char *  end,
char *  start
 

void error_line char *  s  ) 
 

void error_state char *  s  ) 
 

void get_host_port char *  adr,
char *  host,
char *  port
 

Definition at line 1714 of file http_connect.c.

Referenced by log_ACT(), log_END(), and log_SYN().

01715 {
01716  char *fp;
01717  char *fpx;
01718  char adr_field[50];
01719 
01720  strcpy(adr_field, adr);
01721  /* break string at '.' separating host and port fields (last in string) */
01722  fp = (char *)rindex(adr_field, '.');
01723  *fp = '\0';   /* replace '.' with string terminator */
01724  strcpy(host, adr_field); /* copies host name up to terminator */ 
01725 
01726  fp++;  /* move pointer past terminator to 1st char in port field */
01727  fpx = (char *)index(fp, ':');   /* see if we have the ':' after a dst port */
01728  if (fpx != NULL)
01729      *fpx = '\0';  /* if so, replace with string terminator */
01730  strcpy(port, fp); 
01731 }

int get_sequence char *  p,
unsigned long *  begin,
unsigned long *  end,
unsigned long *  bytes
 

Definition at line 1733 of file http_connect.c.

Referenced by parse_dump_record().

01735 {
01736  char seq_field[50];
01737  char *cursor = seq_field;
01738  char *fp;
01739 
01740  strcpy (seq_field, p);
01741 
01742  fp = (char *)strsep(&cursor, ":" );
01743  if ((cursor == (char *)NULL) ||
01744      (fp == (char *)NULL))
01745     return (-1);
01746  else
01747     *begin = strtoul(fp, (char **)NULL, 10);
01748 
01749  fp = (char *)strsep(&cursor, "(" );
01750  if ((cursor == (char *)NULL) ||
01751      (fp == (char *)NULL))
01752     return (-1);
01753  else
01754     *end = strtoul(fp, (char **)NULL, 10);
01755 
01756  fp = (char *)strsep(&cursor, ")" );
01757  if ((cursor == (char *)NULL) ||
01758      (fp == (char *)NULL))
01759     return (-1);
01760  else
01761     *bytes = strtoul(fp, (char **)NULL, 10);
01762  return(0);
01763 }

void init_active void   ) 
 

Definition at line 1165 of file http_connect.c.

References FIN_sent_time, have_ACK_error, have_FINdata_error, have_value_error, last_connection_time, and RST_sent_time.

Referenced by main().

01166 {
01167  strcpy(FIN_sent_time, "");
01168  strcpy(RST_sent_time, "");
01169  strcpy(last_connection_time, "");
01170 
01171  have_ACK_error = 0;
01172  have_value_error = 0;
01173  have_FINdata_error = 0;
01174 
01175 }

void init_connection void   ) 
 

Definition at line 1131 of file http_connect.c.

References begin_seq, connection_state, current_request_end, current_response_end, current_synseq, error_line(), FIN_sent_time, has_seq, have_ACK_error, have_FINdata_error, have_value_error, last_connection_time, last_request_end, last_response_end, log_SYN(), RST_sent_time, and SYN_SENT.

Referenced by check_tuple_reuse(), and main().

01132 {
01133  log_SYN();                /* log start of connection */
01134  connection_state = SYN_SENT;  /* new connection state */
01135 
01136  /* save SYN sequence number for duplicate detection */
01137  if (has_seq == 1)
01138      current_synseq = begin_seq;
01139  else
01140      error_line ("SYN without valid sequence #");
01141 
01142  /* assume tcpdump relative addressing and initialize */
01143  /* note that initializing to 1 instead of 0 adjusts for ACK
01144     being the next expected sequence number */
01145 
01146  last_request_end = 1;       /* need "last" and "current" */
01147  last_response_end = 1;      /* values since there may be */
01148  current_response_end = 1;   /* > 1 request per connection */
01149  current_request_end = 1;
01150 
01151  strcpy(FIN_sent_time, "");
01152  strcpy(RST_sent_time, "");
01153  strcpy(last_connection_time, "");
01154 
01155  have_ACK_error = 0;
01156  have_value_error = 0;
01157  have_FINdata_error = 0;
01158 }

Here is the call graph for this function:

void log_ACT char *  how  ) 
 

Definition at line 1665 of file http_connect.c.

References act_req_count, act_rsp_count, current_dst, current_src, dst_host, dst_port, get_host_port(), outFP, src_host, src_port, and ts.

Referenced by main().

01666 {
01667 /* parse sourse host/port */
01668   get_host_port(current_src, src_host, src_port);
01669 
01670 /* parse destination host/port */
01671   get_host_port(current_dst, dst_host, dst_port);
01672 
01673   /* for activity on a SYN-less connection we record the tcpdump timestamp
01674      of the first record of activiy associated with that conneciton along
01675      with the TCP connection 4-tuple and the way the connection started
01676      (Request or Response). */
01677 
01678   fprintf(outFP, "%s %-15s %5s > %-15s %4s: ACT-%s\n", ts, 
01679                                     dst_host, dst_port, src_host, src_port,  
01680                                     how);
01681   if (strcmp(how, "REQ") == 0)
01682      act_req_count++;
01683   else
01684      if (strcmp(how, "RSP") == 0)
01685         act_rsp_count++;
01686 }

Here is the call graph for this function:

void log_connection void   ) 
 

Definition at line 1473 of file http_connect.c.

References connection_state, current_response_end, FIN_SENT, have_pending_acks, have_pending_fins, have_pending_othr, have_pending_rsts, IN_REQUEST, IN_RESPONSE, last_response_end, last_state, log_END(), log_REQ(), log_RSP(), PENDING, pending_ack_count, pending_cmb_count, pending_fin_count, pending_oth_count, pending_rst_count, and RESET.

Referenced by main().

01474 {
01475 /* if no more tcpdump records found while processing an http
01476    request, log (perhaps incomplete) client request */  
01477 
01478    if (connection_state == IN_REQUEST)
01479       log_REQ();
01480    else
01481       {
01482        /* if no more records found while processing an http 
01483           response, log (perhaps incomplete) response information */
01484 
01485        if ((connection_state == IN_RESPONSE) ||
01486            ((connection_state == RESET) && last_state == IN_RESPONSE))
01487       { /* don't log if just ACKed 1 (assume  FIN) */
01488            if (current_response_end > (last_response_end + 1))
01489                log_RSP();
01490           }
01491       }
01492 
01493    /* make log entry indicating type of connection termination;
01494       entry for connection is made only if a valid start (SYN) was
01495       previously recognized */ 
01496 
01497    if (connection_state != PENDING)  /* saw SYN */
01498       {
01499        if (connection_state == FIN_SENT) 
01500            log_END("FIN");
01501        else
01502       {
01503            if (connection_state == RESET) 
01504                log_END("RST");
01505            else
01506                log_END("TRM");
01507       }
01508       }
01509    else
01510       {
01511        if (((have_pending_fins > 0) +
01512             (have_pending_rsts > 0) +
01513             (have_pending_othr > 0) +
01514             (have_pending_acks > 0)) > 1)
01515           pending_cmb_count++;
01516        else
01517       {
01518            pending_fin_count += (have_pending_fins > 0);
01519            pending_rst_count += (have_pending_rsts > 0);
01520            pending_ack_count += (have_pending_acks > 0);
01521            pending_oth_count += (have_pending_othr > 0);
01522           }
01523       }
01524 }

Here is the call graph for this function:

void log_END char *  how  ) 
 

Definition at line 1624 of file http_connect.c.

References current_dst, current_src, dst_host, dst_port, fin_count, FIN_sent_time, get_host_port(), last_connection_time, outFP, rst_count, RST_sent_time, src_host, src_port, and trm_count.

Referenced by check_tuple_reuse(), and log_connection().

01625 {
01626   char logical_end_time[20];
01627   
01628 /* parse sourse host/port */
01629   get_host_port(current_src, src_host, src_port);
01630 
01631 /* parse destination host/port */
01632   get_host_port(current_dst, dst_host, dst_port);
01633 
01634   if (strcmp(how, "FIN") == 0)
01635      {
01636       fin_count++;
01637       strcpy(logical_end_time, FIN_sent_time);
01638      }
01639   else
01640     {
01641      if (strcmp(how, "RST") == 0)
01642         {
01643          rst_count++;
01644          strcpy(logical_end_time, RST_sent_time);
01645         }
01646      else
01647         if (strcmp(how, "TRM") == 0)
01648        {
01649             trm_count++;
01650             strcpy(logical_end_time, last_connection_time);
01651            }
01652     }
01653 
01654   /* for termination of a connection we record the tcpdump timestamp of
01655      the last record of any kind associated with that conneciton along
01656      with the TCP connection 4-tuple and the way the connection ended
01657      (FIN, Reset, or just no more records in the trace). */
01658 
01659   fprintf(outFP, "%s %-15s %5s > %-15s %4s: %s               %s\n", 
01660                                     last_connection_time, 
01661                                     dst_host, dst_port, src_host, src_port,  
01662                                     how, logical_end_time);
01663 }

Here is the call graph for this function:

void log_log void   ) 
 

Definition at line 1527 of file http_connect.c.

References act_req_count, act_rsp_count, err_count, fin_count, input_name, logFP, output_name, pending_ack_count, pending_cmb_count, pending_fin_count, pending_oth_count, pending_rst_count, req_count, rsp_count, rst_count, syn_count, and trm_count.

Referenced by main().

01528 {
01529  fprintf(logFP, "Input tcpdump file: %s \n", input_name);
01530  fprintf(logFP, "Output connection file: %s \n", output_name);
01531  fprintf(logFP, "   SYNs     %8d \n", syn_count);
01532  fprintf(logFP, "   REQs     %8d \n", req_count);
01533  fprintf(logFP, "   ACT-REQs %8d \n", act_req_count);
01534  fprintf(logFP, "   RSPs     %8d \n", rsp_count);
01535  fprintf(logFP, "   ACT-RSPs %8d \n", act_rsp_count);
01536  fprintf(logFP, "   FINs     %8d \n", fin_count);
01537  fprintf(logFP, "   RSTs     %8d \n", rst_count);
01538  fprintf(logFP, "   TRMs     %8d \n", trm_count);
01539  fprintf(logFP, "   ERRs     %8d \n", err_count);
01540  fprintf(logFP, "Partial Connections:\n");
01541  fprintf(logFP, " FIN only   %8d \n", pending_fin_count);
01542  fprintf(logFP, " RST only   %8d \n", pending_rst_count);
01543  fprintf(logFP, " ACK only   %8d \n", pending_ack_count);
01544  fprintf(logFP, " Combos     %8d \n", pending_cmb_count);
01545  fprintf(logFP, " Other      %8d \n", pending_oth_count);
01546 }

void log_nosyn void   ) 
 

void log_REQ void   ) 
 

void log_RSP void   ) 
 

void log_SYN void   ) 
 

Definition at line 1611 of file http_connect.c.

References current_dst, current_src, dst_host, dst_port, get_host_port(), outFP, src_host, src_port, syn_count, and ts.

Referenced by init_connection().

01612 {
01613 /* parse sourse host/port */
01614   get_host_port(current_src, src_host, src_port);
01615 
01616 /* parse destination host/port */
01617   get_host_port(current_dst, dst_host, dst_port);
01618 
01619   fprintf(outFP, "%s %-15s %5s > %-15s %4s: SYN\n", ts, 
01620                                      dst_host, dst_port, src_host, src_port);  
01621   syn_count++;
01622 }

Here is the call graph for this function:

void main int  argc,
char *  argv[]
 

Definition at line 249 of file http_connect.c.

References ACK_ONLY, begin_REQ(), begin_RSP(), check_ACK_advance(), check_tuple_reuse(), connection_state, current_dst, current_request_end, current_response_end, current_src, current_synseq, DATA_ACK, dh, dumpFP, end_seq, error_state(), FIN, FIN_SENT, FIN_sent_time, fl, gt, has_ack, has_seq, have_FINdata_error, have_pending_acks, have_pending_fins, have_pending_othr, have_pending_rsts, IN_REQUEST, IN_RESPONSE, init_active(), init_connection(), input_name, input_type, last_connection_time, last_request_end, last_response_end, last_state, log_ACT(), log_connection(), log_log(), log_name, log_REQ(), log_RSP(), logFP, more_REQ(), more_RSP(), new_ack, new_address, new_line, outFP, output_name, p1, p2, p3, parse_dump_record(), PENDING, rc, request_end_time, RESET, response_end_time, RST, RST_sent_time, seq_bytes, sh, start_request_time, start_response_time, SYN, SYN_SENT, ts, and Usage().

00250 {
00251   int i;
00252 
00253   /* Parse the command line */
00254   i = 1;
00255   while (i < argc) {
00256     if (strcmp (argv[i], "-r") == 0) {
00257       /* -r flag is followed by name of file to read */
00258       if (++i >= argc) Usage (argv[0]);
00259       strcpy (input_name, argv[i]);
00260     }
00261     else if (strcmp (argv[i], "-w") == 0) {
00262       /* -w flag is followed by the name of file to write */
00263       if (++i >= argc) Usage (argv[0]);
00264       strcpy (output_name, argv[i]);
00265     }
00266     else 
00267       Usage (argv[0]);
00268     i++;
00269   }
00270 
00271   /* Open files */
00272   /* Note: program is written to also be used as a filter */
00273 
00274   if (strcmp(output_name, "") == 0) 
00275     /* if no explicit output file named with -w, use stdout */
00276      outFP = stdout;
00277   else 
00278      {
00279       if ((outFP = fopen (output_name, "w")) == NULL) {
00280           fprintf (stderr, "error opening %s\n", output_name);
00281           exit (-1);
00282           }
00283      }
00284 
00285   if (strcmp(input_name, "") == 0)
00286     /* if no explicit input file named with -r, use stdin */
00287      dumpFP = stdin;
00288   else 
00289      {
00290       if ((dumpFP = fopen (input_name, "r")) == NULL) {
00291           fprintf (stderr, "error opening %s\n", input_name);
00292           exit (-1);
00293          }
00294      }
00295   
00296   strcpy(log_name, output_name);
00297   strcat(log_name, ".log");
00298   if ((logFP = fopen (log_name, "w")) == NULL) {
00299       fprintf (stderr, "error opening %s\n", log_name);
00300       exit (-1);
00301      }
00302 
00303   /* begin main loop; once through loop for each line in the tcpdump */
00304   /* a <continue> anywhere in the loop (usually after an error case)
00305      implies beginning of processing a new tcpdump record */
00306 
00307   while (!feof (dumpFP)) {
00308 
00309 /* printf("State is %d, last_state is %d\n", connection_state, last_state); */
00310 
00311     /* Get and parse line of tcpdump file */
00312 
00313     fgets (new_line, sizeof(new_line), dumpFP);
00314 
00315     /* get line pieces; this works because there are always 8 or more 
00316        fields separated by white space in tcpdump ASCII-format lines */
00317 /*    sscanf (new_line, "%s %s %s %s %s %s %s %s %s",
00318                       &ts, &lt, &sh, &gt, &dh, &fl, &p1, &p2, &p3);
00319 */
00320     sscanf (new_line, "%s %s %s %s %s %s %s %s",
00321                       &ts, &sh, &gt, &dh, &fl, &p1, &p2, &p3);
00322 
00323    /* If any part of the connection tuple (source host.port,destination
00324       host.port) differs from the current values, there are no more 
00325       tcpdump records for that connection so treat as end of connection.
00326       The action taken at the end of a connection depends on the current
00327       state of processing in that connection */  
00328 
00329    if ((strcmp(current_src, sh) != 0) ||  /* new source host/port */
00330        (strcmp(current_dst, dh) != 0))    /* new dest. host/port */
00331        {
00332         log_connection(); 
00333 
00334         /* begin processing this record as being from a potential new
00335            TCP connection so initialize connection's state */
00336 
00337         strcpy(current_src, sh);  /* new connection tuple */
00338         strcpy(current_dst, dh);  /* host and port for src & dest */
00339 
00340         have_pending_acks = 0;
00341         have_pending_fins = 0;
00342         have_pending_rsts = 0;
00343         have_pending_othr = 0;
00344 
00345         current_synseq = 0;
00346         connection_state = PENDING;  /* unconnected pending a SYN */
00347         last_state = PENDING;
00348         new_address = 1;        /* true only for very first record
00349                                    from a different TCP connection -- 
00350                                    avoids multiple error messages */
00351        }
00352    
00353    /* break dump record into essential data fields; initializes the
00354       following variables: begin_seq, end_seq, seq_bytes, new_ack,
00355                            has_ack, has_seq, input_type.
00356       Also checks for suspect sequence and ACK values.
00357    */
00358 
00359    if ((rc = parse_dump_record()) < 0) 
00360        continue;
00361 
00362    /* processing records from a TCP connections is based on a notion of
00363       the current "state" of the connection.  The defined states are
00364         PENDING := record is from different connection than before but
00365                    a beginning SYN has not yet been identified.
00366         SYN_SENT:= have identified SYN sent from source port 80 (server)
00367         FIN_SENT:= have identified a FIN sent from source port 80 (server)
00368                    This terminates any data from server.
00369         RESET   := have identified a Reset sent from source port 80 (server)
00370                    This means that the server should not accept any more
00371                    client data.
00372         IN_REQUEST := processing ACKs sent from source port 80 (server)
00373                       in response to data (request) from the client.  In
00374                       this state, need to identify end of client data (request)
00375                       and start of server data (response).
00376         IN_RESPONSE := processing data sequence #s from source port 80
00377                        In this state, need to identify the end of server data
00378                        (response) and, possibly the beginning of a new request.
00379       Whenever the state changes, the prior state is also noted.
00380 
00381       Fundamental to all of this is the notion that a server cannot  
00382       possibly be sending data in response to a request unless that
00383       data is accompanied or preceeded by an advance in the ACK sequence
00384       indicating receipt of the request data.  Similarly, we assume that
00385       any new data sent by a server that follows or is accompanied by an
00386       advance in the ACK sequence number is a response to the request 
00387       that caused the ACK sequence to advance.  Put another way, response
00388       data (sequence # advance) marks the end of a request and ACK 
00389       advance marks the end of a response.  Of course other events such
00390       as FIN or Reset can mark ends also.  The use of ACK advance to mark
00391       the end of a response assumes that HTTP/1.1 browsers don't overlap 
00392       requests on a single TCP connection even if they may "batch" requests, 
00393       i.e., a new request will not be generated until the response has 
00394       been received. If requests and responses are batched but not 
00395       overlapped this will understate the number of objects requested 
00396       and overstate request and response sizes.
00397 
00398       This use of advancing sequence numbers (ACK or data) to mark
00399       requests and responses is disturbed by segment reorderings in 
00400       the network.  In some cases, such as reordering of only data segments
00401       in a response, there is no problem since only the highest value seen
00402       is used.  Reordering of ACKs (especially with data) presents real
00403       problems since boundaries between requests and responses are missed
00404       which can result in overstating request and response sizes.  For this
00405       reason, all such cases of ACK misordering are logged and reported.
00406    */
00407 
00408    switch (connection_state)
00409 
00410      /* a <break> anywhere ends processing of the current tcpdump record 
00411         by ending the switch (which continues the main read loop) */
00412 
00413       {
00414        case PENDING:
00415      {
00416           switch (input_type)
00417              {
00418          case FIN:
00419             {
00420          /* Ignore random FIN before something useful */ 
00421 
00422                  have_pending_fins++;
00423                  break;
00424                 }
00425 
00426          case SYN:
00427             {
00428           /* normal connection start, initialize connection state */
00429 
00430                  init_connection();
00431                  break;
00432         }
00433 
00434          case RST:
00435                 {
00436           /* Ignore random Reset before something useful */
00437 
00438                  have_pending_rsts++;
00439                  break;
00440                 }
00441 
00442              /* The trace may start after a connection is established and we
00443                 do not see a SYN.  Determine if the connection is most likely
00444                 in a request or in a response and log its status.  As before,
00445                 a request is indicated if the ACK sequence (after the first
00446                 one in the trace) is advancing and a response is indicated if
00447                 the data sequence number is advancing. */
00448 
00449              case ACK_ONLY:
00450             {
00451                   /* ignore initial ACK (has absolute value, not relative) */
00452 
00453                  if (new_address == 1)
00454            {
00455                     new_address = 0;
00456                     have_pending_acks++;
00457                    }
00458                  else
00459             {
00460              /* If ACK advances, the connection is in a request */
00461 
00462                      if ((new_ack > 2) &&
00463                          (new_ack < 16384))
00464                 {
00465                          log_ACT("REQ");
00466 
00467                          last_request_end = 1;
00468                          current_request_end = new_ack;
00469 
00470                          last_response_end = 1;
00471                          current_response_end = 1;
00472 
00473                        /* record the request start time as beginning at the 
00474                           tcpdump time stamp on this record */
00475 
00476                           strcpy(start_request_time, ts);
00477                           strcpy(request_end_time, ts);
00478 
00479                           last_state = connection_state;
00480                           connection_state = IN_REQUEST;
00481  
00482                           init_active();  /* initialize connection state */
00483              }
00484                      else /* ignore ACKs that are not advancing */
00485                         have_pending_acks++;
00486             }
00487                  break;
00488                 }
00489 
00490          case DATA_ACK:          
00491             {
00492          /* If data sequence advances, connection is in response */
00493 
00494                  if ((seq_bytes > 1) &&
00495                      (seq_bytes < 65535))
00496             {
00497                      log_ACT("RSP");
00498 
00499                      /* assume tcpdump relative addressing and initialize */
00500 
00501                      last_request_end = 1;    
00502                      current_request_end = 1;
00503 
00504                      last_response_end = 0;     
00505                      current_response_end = seq_bytes;
00506 
00507                      /* record timestamp of tcpdump record as current
00508                         value of both start and end times of response
00509                         (in case no later end time is found) */
00510 
00511                      strcpy(start_response_time, ts); 
00512                      strcpy(response_end_time, ts);
00513 
00514                      last_state = connection_state;
00515                      connection_state = IN_RESPONSE;
00516  
00517                      init_active();
00518                     }
00519                  else /* ignore data lengths of 0 or 1 */
00520                     have_pending_othr++;
00521                  break;
00522                 }
00523          default:
00524                 break;
00525              }  /* end switch on input_type */
00526           break;
00527      } /* end case PENDING */
00528 
00529        case SYN_SENT:
00530          {
00531 
00532          /* Treat this case as the establishment of a connection.  Usually
00533             the first activity on the connection will be request data from
00534             the client, but some servers appear to "pre-send" data (maybe
00535             the headers) speculatively before ACKing any client data. */
00536 
00537           switch (input_type)
00538              {
00539          case FIN:
00540 
00541               /* A FIN marks the end of either or both request and response */
00542 
00543             {
00544                  if ((has_ack == 1) &&
00545                      (new_ack > (current_request_end + 1)))
00546                                /* ignore possible ACK of FIN */
00547 
00548                { /* this record had advanced the ACK sequence so
00549                         save current request data and log it (since
00550                         the FIN ends the connection it also ends the 
00551                         request). */
00552                
00553                      begin_REQ();
00554                      log_REQ();
00555                     }
00556 
00557                  /* If the data sequence number advances, then there was
00558                     response data.  Save the current response info. and
00559                     log it (since the FIN ends the connection, it also
00560                     ends the response). */
00561 
00562                  if ((has_seq == 1) &&
00563                      (end_seq > current_response_end))  
00564             {
00565                      begin_RSP();
00566                      log_RSP();
00567                     }
00568                  last_state = SYN_SENT;
00569                  connection_state = FIN_SENT;
00570 
00571                  /* record timestamp of first FIN seen on connection */
00572                  if (strcmp(FIN_sent_time, "") == 0)
00573                     strcpy(FIN_sent_time, ts);
00574                  break;
00575                 }
00576 
00577          case SYN:
00578             {
00579           /* In some cases the same host/port pairs are reused in a
00580                      single trace; check for plausible reuse */
00581 
00582                  check_tuple_reuse();
00583                  break;
00584         }
00585 
00586          case RST:
00587                 {
00588                  connection_state = RESET;
00589                  last_state = SYN_SENT;
00590 
00591                  /* record timestamp of first Reset on the connection */
00592 
00593                  if (strcmp(RST_sent_time, "") == 0)
00594                     strcpy(RST_sent_time, ts);
00595                  break;
00596                 }
00597 
00598              case ACK_ONLY:
00599             {
00600                  /* since there is no data sequence # present in the record
00601                     and, therefore, the server is not sending data so
00602                     all the client's data may not have arrived.  Note the
00603                     current extent of ACKed client data and change state */
00604 
00605                  if (new_ack > (current_request_end + 1))
00606                     begin_REQ();
00607                  break;
00608                 }
00609 
00610          case DATA_ACK:          
00611             {
00612                 /* check for presence of data sequence # in the common cases
00613                    in SYN_SENT state, data presence indicates that 
00614                    request data has been received and server is sending data
00615                    that should be a response */
00616 
00617                  if (new_ack > (current_request_end + 1)) 
00618                 {/* this record had advanced the ACK sequence so
00619                      save current request info. and change state */
00620 
00621                      begin_REQ();
00622 
00623                      /* the server's data sequence may not have advanced;
00624                         but if it has, treat it as the start of a response
00625                         and the end of the client (request) data */
00626 
00627                      if (end_seq > current_response_end)
00628                 {
00629                           /* start of response ends the request, log
00630                           it and change state to look for end of response */  
00631 
00632                          log_REQ();
00633                          begin_RSP();
00634                 }
00635             }
00636                  else 
00637            /* some servers appear to send response data immediately
00638                       on completing the TCP connection without receiving 
00639                       any request data */
00640 
00641                     if ((end_seq > last_response_end) && 
00642                         (seq_bytes > 0))
00643                        begin_RSP();
00644                 break;
00645         }
00646          default:
00647                 break;
00648          } /* end switch on input type */
00649           break;
00650      } /* end case SYN_SENT */
00651 
00652        case FIN_SENT:
00653       {
00654            switch (input_type)
00655               {
00656            case SYN:
00657               {
00658           /* In some cases the same host/port pairs are reused in a
00659                      single trace; check for plausible reuse */
00660 
00661                    check_tuple_reuse();
00662                    break;
00663           }
00664 
00665             case FIN:  /* ignore multiple FINs */
00666                    break;
00667 
00668                 case RST:  /* ignore reset after FIN */
00669                    break;
00670 
00671             case ACK_ONLY:
00672                     /* If there is an ACK (only) coming after a FIN is sent, it
00673                       is ether the normal one in the 4-way termination or it
00674                       is to ACK more request data which will be ignored (there
00675                       can be no response).  
00676                       In either case, it is ignored here. */
00677 
00678                    break;
00679 
00680             case DATA_ACK:
00681           {
00682 
00683               /* All others may have sequence number fields.  Treat them as
00684                  errors if they advance the sequence number after a FIN.  
00685                  The usual case here is just retransmissions (including 
00686                  retransmission of the FIN) which should not advance it
00687                  because the highest sequence number possible was on the FIN */
00688 
00689                    if ((end_seq > (current_response_end + 2)) &&
00690                        (have_FINdata_error == 0))
00691               {
00692                        error_state("new data in FIN_SENT state");
00693                        have_FINdata_error = 1;
00694                       }
00695                    break;
00696           }
00697             default:
00698                    break;
00699           } /* end switch on input type */
00700             break; 
00701       } /* end case FIN_SENT */
00702 
00703        case RESET:
00704        {
00705         /* A Reset nominally means an abnormal close of the connection 
00706                with any queued data discarded before transmitting it.  We
00707                observe, however, that under some (unknown) circumstances
00708                segments that advance the data sequence number continue in 
00709                the trace after the Reset.  If these are part of a response, 
00710                it makes sense to count them in the response size since 
00711                the server obviously sent them and the network has to handle 
00712                them.  This also means that a FIN following the Reset may be
00713                a valid indication of the end of a response. Just ignore 
00714                anything else unexpected (e.g., Reset) */
00715 
00716             switch (input_type)
00717                {
00718             case RST:
00719                    break;
00720 
00721             case SYN:
00722               {
00723           /* In some cases the same host/port pairs are reused in a
00724                      single trace; check for plausible reuse */
00725 
00726                    check_tuple_reuse();
00727                    break;
00728           }
00729 
00730             case ACK_ONLY:
00731 
00732                /* an ACK might advance possibly indicating a request.  However,
00733                   since the connection is Reset and there should be no new
00734                   response, just ignore it */
00735 
00736                     break;
00737 
00738             case FIN:
00739           {
00740 
00741             /* Only if the state is IN_RESPONSE do we try to continue looking
00742                for the end of the response.  FIN is treated as the true end
00743                of a response. */
00744 
00745                    if (last_state == IN_RESPONSE)
00746                   {/* ends the current response, ignore any ACK */
00747                        if ((has_seq == 1) &&
00748                            (end_seq > current_response_end)) 
00749                           more_RSP();
00750                        log_RSP();
00751           
00752                        last_state = RESET;
00753                        connection_state = FIN_SENT;
00754 
00755                        /* record timestamp of first FIN on connection */
00756 
00757                        if (strcmp(FIN_sent_time, "") == 0)
00758                           strcpy(FIN_sent_time, ts);
00759               }
00760                     break;
00761            }
00762 
00763            case DATA_ACK:
00764                  {
00765                 /* segments with data may advance the data sequence number as 
00766                    more parts of the response.  They may also advance the ACK
00767                    which normally would indicate a new request.  However,
00768                    after a Reset, it probably will be ignored by the 
00769                    server so it is also ignored here except to mark the end
00770                    of the response. */
00771 
00772                    if (last_state == IN_RESPONSE)
00773               {
00774                        if (new_ack > (last_request_end + 1)) /* new request */
00775                           { /* implies end of current response */
00776                            log_RSP(); 
00777                            last_state = RESET; /* will ignore all else */
00778                            break; 
00779                           }
00780  
00781                      /* As long as the data sequence # advances, continue to
00782                         save info about the current response. */
00783 
00784                        if ((end_seq > current_response_end) &&
00785                            (seq_bytes > 0))
00786                           more_RSP();
00787                       }
00788                   break;
00789          }
00790                default:
00791                   break;
00792            } /* end switch on input type */
00793             break;
00794            } /* end case RESET */
00795 
00796        case IN_RESPONSE:
00797        {
00798             /* In this state, look for events that will indicate the end of
00799                the response data (ACK advances for request, FIN, Reset).  If
00800                the event is ACK advance, this also initiates the start of a
00801                new request.  */
00802 
00803             switch (input_type)
00804                {
00805             case FIN:
00806           {         
00807                    /* FIN is complicated since the segment that carries it may
00808                     also advance the ACK (new request), advance the data
00809                     sequence # and end the connection.  If the ACK advances,
00810                     any sequence # advance is for the new request; otherwise
00811                     a sequence # advance extends and completes the current 
00812                     response. */
00813 
00814                    if (has_ack == 1) 
00815               {
00816                if ((rc = check_ACK_advance(current_request_end)) < 0)
00817                           break;
00818                       }
00819 
00820            /* The ACK advance amount has to be greater than 1 to be
00821                      considered a real new request.  This is primarily to
00822                     filter out just an ACK for a FIN from the client.  Note
00823                     the ACK must advance so duplicate ACKs are ignored. */
00824 
00825                    if ((has_ack == 1) &&
00826                        (new_ack > (current_request_end + 1)))
00827                       { /* implies end of current response, begin request 
00828                            Log the info. for the current response. */
00829 
00830                        log_RSP();  /*end of previous response */
00831 
00832                        /* on FIN, assume end of request also since server is
00833                           closing the connection. */
00834 
00835                        begin_REQ();
00836                        log_REQ(); 
00837 
00838                        /* if the data sequence # also advances, this segment
00839                           (only -- because of the FIN) carries the last part
00840                           of the response */
00841  
00842                        if ((has_seq == 1) &&
00843                            (end_seq > last_response_end)) 
00844                           {/* response begins and ends in the FIN segment */
00845                            begin_RSP();
00846                            log_RSP();  /* also end of any response */
00847                           }
00848 
00849                        /* Note that the null "else" here is the case that the
00850                           data sequence # does not advance (there is no 
00851                           response to the request) -- probably an HTTP/1.1
00852                           broswer attempting multiple requests on a TCP 
00853                           connection where the server doesn't play nice. */
00854 
00855                       }
00856                    else 
00857                       /* the ACK did not advance so no request; if the data
00858                        sequence # advances, it extends the current response */
00859 
00860               {
00861                        if ((has_seq == 1) &&
00862                            (end_seq > current_response_end)) 
00863                           more_RSP();
00864                        log_RSP();    /* FIN always implies end of response */
00865                       }
00866 
00867                    last_state = IN_RESPONSE;
00868                    connection_state = FIN_SENT;
00869 
00870                    if (strcmp(FIN_sent_time, "") == 0)
00871                       strcpy(FIN_sent_time, ts);
00872                    break;
00873           }
00874 
00875                case RST:
00876 
00877                  /* Look for a Reset and only change state to RESET to
00878                    continue processing.  This is explained in comments in 
00879                    processing for the RESET state when the last_state is
00880                    IN_RESPONSE. */
00881 
00882              {/* ignore any advance in seq# on Reset */
00883                   /* it may not be wise to trust ACK on RST */
00884 
00885                   last_state = IN_RESPONSE;
00886                   connection_state = RESET;   
00887 
00888                   if (strcmp(RST_sent_time, "") == 0)
00889                      strcpy(RST_sent_time, ts);
00890                   break;
00891                  }
00892 
00893                case SYN:
00894              {
00895           /* In some cases the same host/port pairs are reused in a
00896                      single trace; check for plausible reuse */
00897 
00898                   check_tuple_reuse();
00899                   break;
00900          }
00901 
00902                case ACK_ONLY:
00903 
00904              /* Begin checking for cases where the ACK may advance
00905                     and really indicate that a new request starts. */
00906 
00907                  {
00908           /* The ACK advance amount has to be greater than 1 to be
00909                      considered a real new request.  This is primarily to
00910                      filter out just an ACK for a FIN from the client.  Note
00911                      the ACK must advance so duplicate or OOO
00912                      ACKs are ignored. */
00913 
00914                   if (new_ack > (last_request_end + 1)) 
00915              { /* implies end of current response, begin request.
00916                          Log the info. for the current response and change
00917                          states. */
00918                       log_RSP();
00919 
00920                     /* since there is no data sequence # present in the record
00921                     and, therefore, the server is not sending data so
00922                     all the client's data may not have arrived.  Note the
00923                     current extent of ACKed client data and start time */
00924 
00925                       begin_REQ();
00926                      }
00927                   break;
00928                  }
00929 
00930                case DATA_ACK:
00931 
00932             /* cases with data and ACKs have two important sub-cases: (a) 
00933                ACK sequence number advances -- implies the start of a
00934                new request and the end of the current response; if the
00935                data sequence number also advances, it is assumed that
00936                all the request data has been received and the first of
00937                the response data is contained in the segment. (b) the
00938                ACK sequence number does not advance so any advance in
00939                the data sequence number is more of the current response. */
00940 
00941            {
00942         if ((rc = check_ACK_advance(last_request_end)) < 0)
00943                    break;
00944 
00945          /* The ACK advance amount has to be greater than 1 to be
00946                     considered a real new request.  This is primarily to
00947                     filter out just an ACK for a FIN from the client.  Note
00948                     the ACK must advance so duplicate ACKs are ignored. */
00949 
00950                 if (new_ack > (last_request_end + 1)) 
00951                { /* implies end of current response, begin request 
00952                          Log the info. for the current response. */
00953 
00954                     log_RSP();  
00955                     begin_REQ();
00956 
00957                     /* If there is also new data (sequence # advances), then
00958                        the request is considered completed and a new response
00959                        has started but not necessarily completed. */
00960 
00961                     if ((end_seq > current_response_end) &&
00962                         (seq_bytes > 0))
00963                {/* Log info. about this request */
00964                         log_REQ();
00965                         begin_RSP();
00966                }
00967            }
00968                 else
00969                     /* the ACK did not advance so no request; if the data
00970                        sequence # advances, it extends the current response */
00971 
00972                     if (end_seq > current_response_end) 
00973                        more_RSP();
00974                 break;
00975                }
00976          default:
00977                 break;
00978         } /* end switch on input type */
00979            break;
00980       }  /* end case IN_RESPONSE */
00981 
00982        case IN_REQUEST:
00983        {
00984         /* In this state check for events that indicate the end of the
00985                request data (advance of data sequence #, FIN, Reset).  An
00986                advance in the data sequence # also marks the beginning of
00987                the response to the request */
00988 
00989             switch (input_type)
00990                {
00991             case FIN:
00992 
00993             /* FIN is somewhat less complicated here since the segment that
00994                implies that the server will send no more data.  Treat this
00995                as effectively ending the request.  If the ACK advances, it
00996                is considered as part of the request and if the data 
00997                sequence # advances, it is the response data (all in this
00998                segment). */
00999 
01000             { /* FIN can ACK more of current request */
01001 
01002           /* The ACK advance amount has to be greater than 1 to be
01003                     considered as extending the request.  This is primarily 
01004                     to filter out just an ACK for a FIN from the client.  Note
01005                     the ACK must advance so duplicate ACKs are ignored. */
01006 
01007                  if ((has_ack == 1) &&
01008                      (new_ack > (current_request_end + 1)))
01009                     more_REQ();
01010                  else
01011                     if (has_ack == 1)
01012                {
01013                 if ((rc = check_ACK_advance(current_request_end)) < 0)
01014                            break;
01015                        }
01016 
01017                  log_REQ();  /* on FIN, assume end of request */
01018 
01019                 /* the server's data sequence may not have advanced;
01020                    but if it has, treat it as the complete response */
01021 
01022                  if ((has_seq == 1) &&
01023                      (end_seq > last_response_end))  
01024                     {
01025                      begin_RSP();
01026                      log_RSP();  /* also end of any response */
01027                     }
01028 
01029                  last_state = IN_REQUEST;
01030                  connection_state = FIN_SENT;
01031 
01032                  if (strcmp(FIN_sent_time, "") == 0)
01033                     strcpy(FIN_sent_time, ts);
01034                  break;
01035         }
01036 
01037          case RST:
01038                {
01039                 /* Treat a Reset as ending the request with no response */
01040             /* ignore any advance in ack on Reset */
01041         /* treat as ending any request */
01042 
01043                 log_REQ();                
01044                 last_state = IN_REQUEST;
01045                 connection_state = RESET;
01046 
01047                 if (strcmp(RST_sent_time, "") == 0)
01048                    strcpy(RST_sent_time, ts);
01049                 break;
01050            }
01051 
01052          case SYN:
01053             {
01054          /* In some cases the same host/port pairs are reused in a
01055                     single trace; check for plausible reuse */
01056 
01057                  check_tuple_reuse();
01058                  break;
01059         }
01060 
01061          case ACK_ONLY:
01062             {
01063          /* The ACK advance amount has to be greater than 1 to be
01064                     considered as extending the requesst.  This is primarily 
01065                     to filter out just an ACK for a FIN from the client.  Note
01066                     the ACK must advance so duplicate or OOO 
01067                     ACKs are ignored. */
01068 
01069                  if (new_ack > (current_request_end + 1))
01070                     more_REQ();
01071                  break;
01072                 }
01073 
01074          case DATA_ACK:
01075                {
01076                 /* cases with data and ACKs have two important sub-cases: 
01077                   (a) ACK sequence number advances which extends the amount
01078                   of request data, and (b) the data sequence # advances
01079                   which ends the request and is the beginning of the 
01080                   response to that request. */
01081         /* The ACK advance amount has to be greater than 1 to be
01082                    considered as extending the request.  This is primarily 
01083                    to filter out just an ACK for a FIN from the client.  Note
01084                    the ACK must advance so duplicate ACKs are ignored. */
01085 
01086                 if (new_ack > (current_request_end + 1))
01087                    more_REQ();
01088                 else
01089             if ((rc = check_ACK_advance(current_request_end)) < 0)
01090                        break;
01091 
01092                 /* the server's data sequence may not have advanced;
01093                    but if it has, treat it as the start of a response
01094                    and the end of the request data */
01095 
01096                 if ((end_seq > last_response_end) && 
01097                     (seq_bytes > 0))
01098                    {
01099             /* record info. for current request and change state 
01100                        to look for the end of the response*/
01101 
01102                     log_REQ();
01103                     begin_RSP();
01104                    }
01105                 break;
01106                }
01107          default:
01108                 break;
01109         } /* end switch on input type */ 
01110           break;
01111      }  /* end case IN_REQUEST */
01112 
01113        default:
01114        break;
01115       } /* end switch on connection state */
01116 
01117    /* save the last known time for the connection from current record */
01118    strcpy(last_connection_time, ts); 
01119 
01120  }  /* end main loop */  
01121   log_log();
01122   close (dumpFP);
01123   close (outFP);
01124   close (logFP);
01125 } /* end main() */

Here is the call graph for this function:

void more_REQ void   ) 
 

Definition at line 1288 of file http_connect.c.

References current_request_end, new_ack, request_end_time, and ts.

Referenced by main().

01289 {
01290  current_request_end = new_ack;
01291  strcpy(request_end_time, ts);
01292 }

void more_RSP void   ) 
 

Definition at line 1313 of file http_connect.c.

References current_response_end, end_seq, response_end_time, and ts.

Referenced by main().

01314 {
01315  current_response_end = end_seq;
01316  /* save the new (potential) response end time */
01317  strcpy(response_end_time, ts);
01318 }

int parse_dump_record void   ) 
 

Definition at line 1327 of file http_connect.c.

References ACK_ONLY, begin_seq, connection_state, current_request_end, current_response_end, DATA_ACK, end_seq, error_line(), FIN, fl, get_sequence(), has_ack, has_seq, have_value_error, IN_REQUEST, IN_RESPONSE, input_type, last_state, new_ack, p1, p2, p3, PENDING, rc, RESET, RST, seq_bytes, SYN, and SYN_SENT.

Referenced by main().

01328 {
01329     begin_seq = end_seq = seq_bytes = new_ack = 0;
01330     has_ack = has_seq = 0;
01331 
01332    /* The following flag combinations are flagged because they (a) make no
01333       real sense for SYNs and (b) should be very rare. */
01334 
01335     if ((strcmp(fl, "SFRP") == 0) ||
01336     (strcmp(fl, "SFR") == 0) ||
01337     (strcmp(fl, "SFP") == 0) ||
01338     (strcmp(fl, "SF") == 0) ||
01339     (strcmp(fl, "SRP") == 0) ||
01340     (strcmp(fl, "SR") == 0))
01341        {
01342      /* If out of PENDING state (initial SYN recognized), just note
01343             the error, ignore it and continue.  */
01344 
01345         if (connection_state != PENDING)
01346             error_line ("SYN in combination with F or R");
01347         return(-1);
01348        }
01349 
01350     /* In tcpdump format, the fields coming after flags are, in order,
01351        data-seqno (format "bbb:eee(ccc)") and ack (format "ack xxx").
01352        Both the data-seqno and ack fields may not be present if they
01353        do not have valid information.  If the data-seqno field is not
01354        present, the first field after the flag is the string "ack";
01355        if both are not present the field after the flag is the 
01356        string "win".  Also check to see if tcpdump used absolute instead
01357        of relative values */
01358 
01359     if (strcmp(p1, "ack") == 0)  /* ack and no data sequence no. */
01360        {
01361         has_seq = 0;
01362         has_ack = 1; 
01363         new_ack = strtoul(p2, (char **)NULL, 10);
01364        }
01365     else
01366        {
01367         if (strcmp(p1, "win") == 0) /* no ack, no data */
01368        {
01369             has_ack = 0;
01370             has_seq = 0;
01371            }
01372         else 
01373        {
01374             /* assume it is a valid sequence number field */
01375         /* parse sequence field in header */
01376         /* sequence field format is
01377                <begin_seq #>:<end_seq #>(<seq_bytes count>) */
01378 
01379             if ((rc = get_sequence(p1, &begin_seq, &end_seq, &seq_bytes)) < 0)
01380            {
01381                 error_line ("invalid sequence # field");
01382                 return (-1);
01383                }
01384             has_seq = 1;
01385 
01386             /* check the field following the data sequence # for an ACK */
01387 
01388             if (strcmp(p2, "ack") == 0)  
01389                {
01390                 has_ack = 1; 
01391                 new_ack = strtoul(p3, (char **)NULL, 10);
01392                }
01393             else
01394                has_ack = 0;
01395            }
01396        }
01397 
01398    /* classify flag combinations into equivalence classes for later steps */
01399 
01400       if ((strcmp(fl, "F") == 0) || 
01401           (strcmp(fl, "FP") == 0) ||
01402           (strcmp(fl, "FR") == 0) ||
01403           (strcmp(fl, "FRP") == 0))
01404          input_type = FIN;
01405       else
01406      {
01407           if ((strcmp(fl, "R") == 0) ||
01408               (strcmp(fl, "RP") == 0))
01409              input_type = RST;
01410           else
01411          {
01412               if ((strcmp(fl, "S") == 0) || 
01413                   (strcmp(fl, "SP") == 0))
01414                  input_type = SYN;
01415               else
01416                 {
01417                  if ((has_ack == 1) &&
01418                      (has_seq == 0))
01419                     input_type = ACK_ONLY;
01420                  else
01421                     if ((has_seq == 1) &&
01422                         (has_ack == 1))
01423                        input_type = DATA_ACK;
01424                     else
01425                {   
01426                         error_line("Unexpected Data/ACK combination");
01427                         return (-1);
01428                        }
01429         }
01430          }
01431      }
01432 
01433 
01434       if ((connection_state == IN_RESPONSE) ||
01435           (connection_state == IN_REQUEST) ||
01436           (connection_state == SYN_SENT) ||
01437           ((connection_state == RESET) && (last_state == IN_RESPONSE)))
01438      {   
01439        /* allow for gaps of up to one normal TCP window */
01440 
01441           if (((input_type == FIN) ||
01442                (input_type == DATA_ACK)) &&
01443                (end_seq > (current_response_end + 65535)))
01444          {
01445               if (have_value_error == 0)
01446          {
01447                   error_line ("suspect sequence # value");
01448                   have_value_error = 1;
01449                  }
01450               return (-1);
01451              }
01452 
01453           /* ACK is required for each 2 segments with space for gaps */
01454 
01455           if (((input_type == FIN) ||
01456                (input_type == ACK_ONLY) ||
01457                (input_type == DATA_ACK)) &&
01458                (new_ack > (current_request_end + 16384)))
01459          {
01460               if (have_value_error == 0)
01461          {
01462                   error_line ("suspect ACK value");
01463                   have_value_error = 1;
01464                  }
01465               return (-1);
01466              }
01467          }
01468  return(0);
01469 }

Here is the call graph for this function:

static void tvsub struct timeval *  tdiff,
struct timeval *  t1,
struct timeval *  t0
[static]
 

Definition at line 1770 of file http_connect.c.

01772 {
01773 
01774         tdiff->tv_sec = t1->tv_sec - t0->tv_sec;
01775         tdiff->tv_usec = t1->tv_usec - t0->tv_usec;
01776         if (tdiff->tv_usec < 0)
01777            {
01778             tdiff->tv_sec--;
01779             tdiff->tv_usec += 1000000;
01780            }
01781 }

void Usage char *  s  ) 
 

Definition at line 78 of file http_connect.c.

00079 {
00080   fprintf (stderr,"\nUsage: %s\n", s);
00081   fprintf (stderr,"    [-w file_name] (name for output file)\n");
00082   fprintf (stderr,"    [-r file_name] (name for input file)\n");
00083   fprintf (stderr,"If either -w or -r is omitted, stdout(stdin) is used\n");
00084   fprintf (stderr,"\n");
00085   exit(-1);
00086 }


Variable Documentation

int act_req_count = 0
 

Definition at line 147 of file http_connect.c.

Referenced by log_ACT(), and log_log().

int act_rsp_count = 0
 

Definition at line 148 of file http_connect.c.

Referenced by log_ACT(), and log_log().

unsigned long begin_seq
 

Definition at line 108 of file http_connect.c.

Referenced by check_tuple_reuse(), init_connection(), and parse_dump_record().

enum states connection_state = PENDING
 

Definition at line 169 of file http_connect.c.

Referenced by begin_REQ(), begin_RSP(), check_tuple_reuse(), init_connection(), log_connection(), main(), and parse_dump_record().

char current_dst[25] = ""
 

Definition at line 179 of file http_connect.c.

Referenced by log_ACT(), log_END(), log_SYN(), and main().

unsigned long current_request_end
 

Definition at line 127 of file http_connect.c.

Referenced by begin_REQ(), init_connection(), main(), more_REQ(), and parse_dump_record().

unsigned long current_response_end
 

Definition at line 136 of file http_connect.c.

Referenced by begin_RSP(), init_connection(), log_connection(), main(), more_RSP(), and parse_dump_record().

char current_src[25] = ""
 

Definition at line 175 of file http_connect.c.

unsigned long current_synseq
 

Definition at line 109 of file http_connect.c.

Referenced by check_tuple_reuse(), init_connection(), and main().

char dh[25]
 

Definition at line 100 of file http_connect.c.

char dst_host[25]
 

Definition at line 180 of file http_connect.c.

Referenced by log_ACT(), log_END(), and log_SYN().

char dst_port[10]
 

Definition at line 181 of file http_connect.c.

Referenced by log_ACT(), log_END(), log_SYN(), and IntTcpAgent::send_one().

FILE* dumpFP
 

Definition at line 88 of file http_connect.c.

long elapsed
 

Definition at line 220 of file http_connect.c.

Referenced by check_tuple_reuse(), log_IDLE(), and main().

unsigned long end_seq
 

Definition at line 108 of file http_connect.c.

Referenced by begin_RSP(), main(), more_RSP(), and parse_dump_record().

int err_count = 0
 

Definition at line 146 of file http_connect.c.

Referenced by log_log().

int fin_count = 0
 

Definition at line 143 of file http_connect.c.

Referenced by log_END(), and log_log().

char FIN_sent_time[20]
 

Definition at line 210 of file http_connect.c.

Referenced by init_active(), init_connection(), log_END(), and main().

char fl[5]
 

Definition at line 102 of file http_connect.c.

char gt[3]
 

Definition at line 98 of file http_connect.c.

int has_ack
 

Definition at line 111 of file http_connect.c.

Referenced by main(), and parse_dump_record().

int has_seq
 

Definition at line 111 of file http_connect.c.

Referenced by check_tuple_reuse(), init_connection(), main(), and parse_dump_record().

int have_ACK_error = 0
 

Definition at line 163 of file http_connect.c.

Referenced by check_ACK_advance(), init_active(), and init_connection().

int have_FINdata_error = 0
 

Definition at line 165 of file http_connect.c.

Referenced by init_active(), init_connection(), and main().

int have_pending_acks = 0
 

Definition at line 158 of file http_connect.c.

Referenced by log_connection(), and main().

int have_pending_fins = 0
 

Definition at line 159 of file http_connect.c.

Referenced by log_connection(), and main().

int have_pending_othr = 0
 

Definition at line 161 of file http_connect.c.

Referenced by log_connection(), and main().

int have_pending_rsts = 0
 

Definition at line 160 of file http_connect.c.

Referenced by log_connection(), and main().

int have_value_error = 0
 

Definition at line 164 of file http_connect.c.

Referenced by init_active(), init_connection(), and parse_dump_record().

char input_name[256] = ""
 

Definition at line 214 of file http_connect.c.

Referenced by log_log(), and main().

enum inputs input_type
 

Definition at line 173 of file http_connect.c.

Referenced by main(), and parse_dump_record().

char last_connection_time[20]
 

Definition at line 212 of file http_connect.c.

Referenced by check_tuple_reuse(), init_active(), init_connection(), log_END(), and main().

unsigned long last_request_end
 

Definition at line 127 of file http_connect.c.

Referenced by init_connection(), and main().

unsigned long last_response_end
 

Definition at line 136 of file http_connect.c.

Referenced by init_connection(), log_connection(), and main().

enum states last_state = PENDING
 

Definition at line 170 of file http_connect.c.

Referenced by begin_REQ(), begin_RSP(), check_tuple_reuse(), log_connection(), main(), and parse_dump_record().

struct timeval lastTime = {0,0}
 

Definition at line 92 of file http_connect.c.

char log_name[256] = ""
 

Definition at line 216 of file http_connect.c.

Referenced by main().

FILE* logFP
 

Definition at line 89 of file http_connect.c.

Referenced by log_log(), and main().

char lt[3]
 

Definition at line 99 of file http_connect.c.

Referenced by EmpFtpTrafPool::command().

unsigned long new_ack
 

Definition at line 108 of file http_connect.c.

Referenced by begin_REQ(), check_ACK_advance(), main(), more_REQ(), and parse_dump_record().

int new_address = 0
 

Definition at line 222 of file http_connect.c.

Referenced by main().

char new_line[500]
 

Definition at line 218 of file http_connect.c.

FILE * outFP
 

Definition at line 88 of file http_connect.c.

char output_name[256] = ""
 

Definition at line 215 of file http_connect.c.

Referenced by log_log(), and main().

char p1[50]
 

Definition at line 103 of file http_connect.c.

Referenced by LandmarkAgent::aggregate_tags(), SensorQueryAgent::command(), TfrcSinkAgent::est_loss_EWMA(), main(), parse_dump_record(), FullTcpAgent::predict_ok(), LandmarkAgent::search_tag(), and RNG::U01().

char p2[50]
 

Definition at line 104 of file http_connect.c.

Referenced by LandmarkAgent::aggregate_tags(), SensorQueryAgent::command(), LandmarkAgent::command(), DSDV_Agent::command(), TfrcSinkAgent::est_loss_EWMA(), DSDV_Agent::lost_link(), main(), parse_dump_record(), FullTcpAgent::predict_ok(), LandmarkAgent::search_tag(), and RNG::U01().

char p3[50]
 

Definition at line 105 of file http_connect.c.

Referenced by LandmarkAgent::aggregate_tags(), SensorQueryAgent::command(), main(), parse_dump_record(), FullTcpAgent::predict_ok(), and LandmarkAgent::search_tag().

int pending_ack_count = 0
 

Definition at line 151 of file http_connect.c.

Referenced by log_connection(), and log_log().

int pending_cmb_count = 0
 

Definition at line 153 of file http_connect.c.

Referenced by log_connection(), and log_log().

int pending_fin_count = 0
 

Definition at line 149 of file http_connect.c.

Referenced by log_connection(), and log_log().

int pending_oth_count = 0
 

Definition at line 152 of file http_connect.c.

Referenced by log_connection(), and log_log().

int pending_rst_count = 0
 

Definition at line 150 of file http_connect.c.

Referenced by log_connection(), and log_log().

int rc = 0
 

Definition at line 223 of file http_connect.c.

Referenced by RcHandler::handle(), main(), parse_dump_record(), SessionHelper::recv(), and LDPAgent::recv().

struct timeval recvTime
 

Definition at line 91 of file http_connect.c.

int report_ACK_err = 1
 

Definition at line 76 of file http_connect.c.

Referenced by check_ACK_advance().

int req_count = 0
 

Definition at line 141 of file http_connect.c.

Referenced by log_log().

char request_end_time[20]
 

Definition at line 208 of file http_connect.c.

Referenced by begin_REQ(), main(), and more_REQ().

char response_end_time[20]
 

Definition at line 207 of file http_connect.c.

Referenced by begin_RSP(), main(), and more_RSP().

int rsp_count = 0
 

Definition at line 142 of file http_connect.c.

Referenced by log_log().

int rst_count = 0
 

Definition at line 144 of file http_connect.c.

Referenced by log_END(), and log_log().

char RST_sent_time[20]
 

Definition at line 211 of file http_connect.c.

Referenced by init_active(), init_connection(), log_END(), and main().

unsigned long seq_bytes
 

Definition at line 108 of file http_connect.c.

Referenced by main(), and parse_dump_record().

char sh[25]
 

Definition at line 96 of file http_connect.c.

char src_host[25]
 

Definition at line 176 of file http_connect.c.

Referenced by log_ACT(), log_END(), and log_SYN().

char src_port[10]
 

Definition at line 177 of file http_connect.c.

Referenced by log_ACT(), log_END(), and log_SYN().

char start_request_time[20]
 

Definition at line 188 of file http_connect.c.

Referenced by begin_REQ(), and main().

char start_response_time[20]
 

Definition at line 194 of file http_connect.c.

Referenced by begin_RSP(), and main().

int syn_count = 0
 

Definition at line 140 of file http_connect.c.

Referenced by log_log(), and log_SYN().

int trm_count = 0
 

Definition at line 145 of file http_connect.c.

Referenced by log_END(), and log_log().

char ts[20]
 

Definition at line 94 of file http_connect.c.


Generated on Tue Mar 6 16:53:45 2007 for ns2 Network Simulator 2.29 by  doxygen 1.4.6