📄 http_connect.c
字号:
if (new_ack > (current_request_end + 1)) more_REQ(); else if ((rc = check_ACK_advance(current_request_end)) < 0) break; /* the server's data sequence may not have advanced; but if it has, treat it as the start of a response and the end of the request data */ if ((end_seq > last_response_end) && (seq_bytes > 0)) { /* record info. for current request and change state to look for the end of the response*/ log_REQ(); begin_RSP(); } break; } default: break; } /* end switch on input type */ break; } /* end case IN_REQUEST */ default: break; } /* end switch on connection state */ /* save the last known time for the connection from current record */ strcpy(last_connection_time, ts); } /* end main loop */ log_log(); close (dumpFP); close (outFP); close (logFP);} /* end main() *//* Initialize connection state when a new connection is recognized by the presence of a SYN. */ void init_connection(void){ log_SYN(); /* log start of connection */ connection_state = SYN_SENT; /* new connection state */ /* save SYN sequence number for duplicate detection */ if (has_seq == 1) current_synseq = begin_seq; else error_line ("SYN without valid sequence #"); /* assume tcpdump relative addressing and initialize */ /* note that initializing to 1 instead of 0 adjusts for ACK being the next expected sequence number */ last_request_end = 1; /* need "last" and "current" */ last_response_end = 1; /* values since there may be */ current_response_end = 1; /* > 1 request per connection */ current_request_end = 1; strcpy(FIN_sent_time, ""); strcpy(RST_sent_time, ""); strcpy(last_connection_time, ""); have_ACK_error = 0; have_value_error = 0; have_FINdata_error = 0;}/* Initialize connection state when a new connection is recognized by a change in the host/port 4-tuple, there is no SYN but request or response activity can be determined. Request or response state is initialized in the main program when the type of activity is determined */ void init_active(void){ strcpy(FIN_sent_time, ""); strcpy(RST_sent_time, ""); strcpy(last_connection_time, ""); have_ACK_error = 0; have_value_error = 0; have_FINdata_error = 0;}/* Check for some indications of possible errors such as the ACK appearing to move back -- may indicate out-of-order or something worse. */int check_ACK_advance(unsigned long old_ack){ if ((new_ack < old_ack) && report_ACK_err) { if (have_ACK_error == 0) { error_state("ACK error -- backward"); have_ACK_error = 1; } return(-1); } else return (0);}/* Check to see if reuse of a connection in a trace is reasonable */void check_tuple_reuse(void){ /* ignore duplicate SYNs (have same SYN sequence number) */ if ((has_seq == 1) && (current_synseq != begin_seq)) { /* if a non-duplicate SYN comes before any other activity, treat it as terminating the incomplete connection and starting another */ if ((connection_state == SYN_SENT) || ((connection_state == RESET) && (last_state == SYN_SENT))) { log_END("TRM"); init_connection(); return; } /* It is quite possible to have a valid new connection that reuses the same source and destination IP.port address 4-tuple. Treat this as valid if there has been a FIN from the server or at least 2*MSL has passed since seeing any previous packet from this connection (in case we missed the FIN). If there was a FIN from the server, allow for the case it was an active close by the server (normal for HTTP 1.0), the stack is a BSD derivative, and SO_REUSEADDR is is use (see Stevens vol. 1, pp 245) */ if (connection_state == FIN_SENT) elapsed = 60001; /* force beyond 2MSL test */ else elapsed = elapsed_ms(ts, last_connection_time); if (elapsed < 60000) /* MSL of 30 seconds, minimum */ error_state("Non-duplicate SYN in connection"); else { /* perform all actions associated with the end of one connection and the beginning of the next (see state PENDING) */ switch (connection_state) { case FIN_SENT: log_END("FIN"); break; case RESET: if (last_state == IN_RESPONSE) log_RSP(); log_END("RST"); break; case IN_RESPONSE: log_RSP(); log_END("TRM"); break; case IN_REQUEST: log_REQ(); log_END("TRM"); break; default: break; } init_connection(); } }}/* Record information about the beginning of a new request */void begin_REQ(void){ current_request_end = new_ack; /* record the request start time as beginning at the tcpdump time stamp on this record */ strcpy(start_request_time, ts); strcpy(request_end_time, ts); last_state = connection_state; connection_state = IN_REQUEST;}/* Record information about an in-progress request */void more_REQ(void){ current_request_end = new_ack; strcpy(request_end_time, ts);}/* Record information about the beginning of a new response */void begin_RSP(void){ current_response_end = end_seq; /* record timestamp of tcpdump record as current value of both start and end times of response (in case no later end time is found) */ strcpy(start_response_time, ts); strcpy(response_end_time, ts); last_state = connection_state; connection_state = IN_RESPONSE;}/* Record information about an in-progress response */void more_RSP(void){ current_response_end = end_seq; /* save the new (potential) response end time */ strcpy(response_end_time, ts);}/* Breaks dump record into essential data fields; initializes the following variables: begin_seq, end_seq, seq_bytes, new_ack, has_ack, has_seq, input_type. Also checks for suspect sequence and ACK values.*/int parse_dump_record(){ begin_seq = end_seq = seq_bytes = new_ack = 0; has_ack = has_seq = 0; /* The following flag combinations are flagged because they (a) make no real sense for SYNs and (b) should be very rare. */ if ((strcmp(fl, "SFRP") == 0) || (strcmp(fl, "SFR") == 0) || (strcmp(fl, "SFP") == 0) || (strcmp(fl, "SF") == 0) || (strcmp(fl, "SRP") == 0) || (strcmp(fl, "SR") == 0)) { /* If out of PENDING state (initial SYN recognized), just note the error, ignore it and continue. */ if (connection_state != PENDING) error_line ("SYN in combination with F or R"); return(-1); } /* In tcpdump format, the fields coming after flags are, in order, data-seqno (format "bbb:eee(ccc)") and ack (format "ack xxx"). Both the data-seqno and ack fields may not be present if they do not have valid information. If the data-seqno field is not present, the first field after the flag is the string "ack"; if both are not present the field after the flag is the string "win". Also check to see if tcpdump used absolute instead of relative values */ if (strcmp(p1, "ack") == 0) /* ack and no data sequence no. */ { has_seq = 0; has_ack = 1; new_ack = strtoul(p2, (char **)NULL, 10); } else { if (strcmp(p1, "win") == 0) /* no ack, no data */ { has_ack = 0; has_seq = 0; } else { /* assume it is a valid sequence number field */ /* parse sequence field in header */ /* sequence field format is <begin_seq #>:<end_seq #>(<seq_bytes count>) */ if ((rc = get_sequence(p1, &begin_seq, &end_seq, &seq_bytes)) < 0) { error_line ("invalid sequence # field"); return (-1); } has_seq = 1; /* check the field following the data sequence # for an ACK */ if (strcmp(p2, "ack") == 0) { has_ack = 1; new_ack = strtoul(p3, (char **)NULL, 10); } else has_ack = 0; } } /* classify flag combinations into equivalence classes for later steps */ if ((strcmp(fl, "F") == 0) || (strcmp(fl, "FP") == 0) || (strcmp(fl, "FR") == 0) || (strcmp(fl, "FRP") == 0)) input_type = FIN; else { if ((strcmp(fl, "R") == 0) || (strcmp(fl, "RP") == 0)) input_type = RST; else { if ((strcmp(fl, "S") == 0) || (strcmp(fl, "SP") == 0)) input_type = SYN; else { if ((has_ack == 1) && (has_seq == 0)) input_type = ACK_ONLY; else if ((has_seq == 1) && (has_ack == 1)) input_type = DATA_ACK; else { error_line("Unexpected Data/ACK combination"); return (-1); } } } } if ((connection_state == IN_RESPONSE) || (connection_state == IN_REQUEST) || (connection_state == SYN_SENT) || ((connection_state == RESET) && (last_state == IN_RESPONSE))) { /* allow for gaps of up to one normal TCP window */ if (((input_type == FIN) || (input_type == DATA_ACK)) && (end_seq > (current_response_end + 65535))) { if (have_value_error == 0) { error_line ("suspect sequence # value"); have_value_error = 1; } return (-1);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -