void interception_output_stat(tc_event_timer_t *evt) { tc_log_info(LOG_NOTICE, 0, "total resp packets:%llu, all:%llu", tot_copy_resp_packs, tot_resp_packs); #if (!TCPCOPY_SINGLE) router_stat(); delay_table_delete_obsolete(tc_time()); #endif evt->msec = tc_current_time_msec + OUTPUT_INTERVAL; }
static void remove_obsolete_resources(int is_full) { time_t thresh_access_tme; uint32_t i, cnt = 0; link_list *l; hash_node *hn; p_link_node ln, next_ln; if (ctx.table == NULL || ctx.table->total == 0) { return; } if (is_full) { thresh_access_tme = tc_time() + 1; } else { thresh_access_tme = tc_time() - MAX_IDLE_TIME; } for (i = 0; i < ctx.table->size; i ++) { l = get_link_list(ctx.table, i); if (l->size > 0) { ln = link_list_first(l); while (ln) { hn = (hash_node *) ln->data; next_ln = link_list_get_next(l, ln); if (hn->access_time < thresh_access_tme) { release_resources(hn->key); } ln = next_ln; } cnt += l->size; if (ctx.table->total == cnt) { break; } } } }
static void tc_nl_check_cleaning() { int diff; time_t now; now = tc_time(); diff = now - last_clean_time; if (diff > CHECK_INTERVAL) { route_delete_obsolete(now); last_clean_time = now; } }
static void check_replay_complete() { #if (!GRYPHON_COMET) int diff; if (last_resp_time) { diff = tc_time() - last_resp_time; if (diff > DEFAULT_TIMEOUT) { tc_over = 1; } } #endif }
static void tc_nl_check_cleaning() { int diff; time_t now; now = tc_time(); diff = now - last_clean_time; if (diff > CHECK_INTERVAL) { tc_log_info(LOG_NOTICE, 0, "total response packets:%llu", tot_resp_packs); route_delete_obsolete(now); last_clean_time = now; } }
static tc_user_t * tc_retrieve_active_user() { int total, speed; time_t cur; tc_user_t *u; cur = tc_time(); if (record_time == 0) { record_time = cur; } if (init_phase) { total = base_user_seq + relative_user_seq; if (total >= size_of_users) { tc_log_info(LOG_NOTICE, 0, "total is larger than size of users"); init_phase = false; u = user_array + 0; base_user_seq = 1 % size_of_users; } else { u = user_array + total; speed = clt_settings.conn_init_sp_fact; relative_user_seq = (relative_user_seq + 1) % speed; if (relative_user_seq == 0) { if (record_time != cur) { base_user_seq += speed; record_time = cur; tc_log_info(LOG_NOTICE, 0, "change record time"); total = total + 1; if (total == size_of_users) { init_phase = false; tc_log_info(LOG_NOTICE, 0, "set init phase false"); } } } } } else { u = user_array + base_user_seq; base_user_seq = (base_user_seq + 1) % size_of_users; } return u; }
static void tc_check_cleaning() { int diff; time_t now; now = tc_time(); diff = now - last_clean_time; if (diff > CHECK_INTERVAL) { tc_log_info(LOG_NOTICE, 0, "total resp packets:%llu, all:%llu", tot_copy_resp_packs, tot_resp_packs); #if (!TCPCOPY_SINGLE) route_delete_obsolete(now); #endif last_clean_time = now; } }
static void tc_process_offline_packet(tc_event_timer_t *evt) { int diff = 0; if (!read_pcap_over) { send_packets_from_pcap(0); } else { diff = tc_time() - read_pcap_over_time; if (diff > DEFAULT_SESSION_TIMEOUT) { tc_over = SIGRTMAX; tc_log_info(LOG_NOTICE, 0, "offline replay is complete"); } } evt->msec = tc_current_time_msec; }
void interception_push(tc_event_timer_t *evt) { send_buffered_packets(tc_time()); evt->msec = tc_current_time_msec + CHECK_INTERVAL; }
static bool process_packet(tc_user_t *u, unsigned char *frame) { bool result; uint16_t size_ip, size_tcp, tot_len, cont_len; uint32_t h_ack, h_last_ack; tc_ip_header_t *ip_header; tc_tcp_header_t *tcp_header; ip_port_pair_mapping_t *test; ip_header = (tc_ip_header_t *) (frame + ETHERNET_HDR_LEN); size_ip = ip_header->ihl << 2; tcp_header = (tc_tcp_header_t *) ((char *) ip_header + size_ip); size_tcp = tcp_header->doff << 2; tot_len = ntohs(ip_header->tot_len); cont_len = tot_len - size_tcp - size_ip; if (u->dst_port == 0) { test = get_test_pair(&(clt_settings.transfer), ip_header->daddr, tcp_header->dest); if (test == NULL) { tc_log_info(LOG_NOTICE, 0, " test null:%u", ntohs(tcp_header->dest)); tc_log_trace(LOG_WARN, 0, TO_BAKEND_FLAG, ip_header, tcp_header); return false; } u->dst_addr = test->target_ip; u->dst_port = test->target_port; #if (GRYPHON_PCAP_SEND) u->src_mac = test->src_mac; u->dst_mac = test->dst_mac; #endif } if (u->state.last_ack_recorded) { if (u->state.status < SEND_REQ && (u->state.status & SYN_CONFIRM)) { h_ack = ntohl(tcp_header->ack_seq); h_last_ack = ntohl(u->history_last_ack_seq); if (after(h_ack, h_last_ack)) { tc_log_debug1(LOG_DEBUG, 0, "server resp first, wait, p:%u", ntohs(u->src_port)); u->state.resp_waiting = 1; return false; } } } ip_header->saddr = u->src_addr; tcp_header->source = u->src_port; u->history_last_ack_seq = tcp_header->ack_seq; u->state.last_ack_recorded = 1; tcp_header->ack_seq = u->exp_ack_seq; ip_header->daddr = u->dst_addr; tcp_header->dest = u->dst_port; tc_log_debug2(LOG_DEBUG, 0, "set ack seq:%u, p:%u", ntohl(u->exp_ack_seq), ntohs(u->src_port)); packs_sent_cnt++; if (tcp_header->syn) { syn_sent_cnt++; #if (!GRYPHON_SINGLE) if (!send_router_info(u, CLIENT_ADD)) { return false; } #endif u->state.last_ack_recorded = 0; u->state.status |= SYN_SENT; } else if (tcp_header->fin) { fin_sent_cnt++; u->state.status |= CLIENT_FIN; } else if (tcp_header->rst) { rst_sent_cnt++; u->state.status |= CLIENT_FIN; tc_log_debug1(LOG_DEBUG, 0, "a reset packet to back:%u", ntohs(u->src_port)); } if (cont_len > 0) { cont_sent_cnt++; u->state.status |= SEND_REQ; } if (u->state.timestamped) { update_timestamp(u, tcp_header); } tcp_header->check = 0; tcp_header->check = tcpcsum((unsigned char *) ip_header, (unsigned short *) tcp_header, (int) (tot_len - size_ip)); #if (GRYPHON_PCAP_SEND) ip_header->check = 0; ip_header->check = csum((unsigned short *) ip_header,size_ip); #endif tc_log_debug_trace(LOG_DEBUG, 0, TO_BAKEND_FLAG, ip_header, tcp_header); #if (!GRYPHON_PCAP_SEND) result = tc_raw_socket_send(tc_raw_socket_out, ip_header, tot_len, ip_header->daddr); #else fill_frame((struct ethernet_hdr *) frame, u->src_mac, u->dst_mac); result = tc_pcap_send(frame, tot_len + ETHERNET_HDR_LEN); #endif if (result == TC_OK) { u->last_sent_time = tc_time(); return true; } else { tc_log_info(LOG_ERR, 0, "send to back error,tot_len is:%d,cont_len:%d", tot_len,cont_len); #if (!TCPCOPY_PCAP_SEND) tc_raw_socket_out = TC_INVALID_SOCKET; #endif tc_over = SIGRTMAX; return false; } }
static bool send_stop(tc_user_t *u) { int send_diff; long app_resp_diff; uint32_t srv_sk_buf_s; if (u->orig_frame == NULL) { tc_log_debug1(LOG_DEBUG, 0, "orig frame is null :%d", ntohs(u->src_port)); return true; } if (u->state.status & SYN_SENT) { if (!(u->state.status & SYN_CONFIRM)) { tc_log_debug1(LOG_DEBUG, 0, "client wait server handshake:%d", ntohs(u->src_port)); return true; } } if (u->state.status & CLIENT_FIN) { if (!(u->state.status & SERVER_FIN)) { tc_log_debug1(LOG_DEBUG, 0, "client wait server fin:%d", ntohs(u->src_port)); return true; } } send_diff = tc_time() - u->last_sent_time; if (send_diff >= 3) { tc_log_debug1(LOG_DEBUG, 0, "timeout, need to send more packet:%d", ntohs(u->src_port)); u->state.resp_waiting = 0; return false; } if (u->state.resp_waiting) { tc_log_debug1(LOG_DEBUG, 0, "client wait server resp:%d", ntohs(u->src_port)); return true; } if (u->state.status & SEND_REQ) { if (u->orig_frame->next != NULL) { srv_sk_buf_s = u->orig_frame->next->seq - u->orig_frame->seq; srv_sk_buf_s = srv_sk_buf_s + u->orig_frame->seq - u->last_ack_seq; if (srv_sk_buf_s > u->srv_window) { tc_log_debug3(LOG_DEBUG, 0, "wait,srv_sk_buf_s:%u,win:%u,p:%u", srv_sk_buf_s, u->srv_window, ntohs(u->src_port)); return true; } } } app_resp_diff = tc_milliscond_time() - u->last_recv_resp_cont_time; if (app_resp_diff <= 10) { tc_log_debug1(LOG_DEBUG, 0, "need to wait resp complete:%d", ntohs(u->src_port)); return true; } tc_log_debug1(LOG_DEBUG, 0, "last resort, set stop false:%d", ntohs(u->src_port)); return false; }
void process_outgress(unsigned char *packet) { uint16_t size_ip, size_tcp, tot_len, cont_len; uint32_t seq, ack_seq; uint64_t key; tc_user_t *u; tc_ip_header_t *ip_header; tc_tcp_header_t *tcp_header; last_resp_time = tc_time(); resp_cnt++; ip_header = (tc_ip_header_t *) packet; size_ip = ip_header->ihl << 2; tcp_header = (tc_tcp_header_t *) ((char *) ip_header + size_ip); key = tc_get_key(ip_header->daddr, tcp_header->dest); tc_log_debug1(LOG_DEBUG, 0, "key from bak:%llu", key); u = tc_retrieve_user(key); if (u != NULL) { tc_log_debug_trace(LOG_DEBUG, 0, BACKEND_FLAG, ip_header, tcp_header); u->srv_window = ntohs(tcp_header->window); if (u->wscale) { u->srv_window = u->srv_window << (u->wscale); tc_log_debug1(LOG_DEBUG, 0, "window size:%u", u->srv_window); } if (u->state.timestamped) { retrieve_options(u, REMOTE, tcp_header); } size_tcp = tcp_header->doff << 2; tot_len = ntohs(ip_header->tot_len); cont_len = tot_len - size_tcp - size_ip; if (ip_header->daddr != u->src_addr || tcp_header->dest!= u->src_port) { tc_log_info(LOG_NOTICE, 0, " key conflict"); } seq = ntohl(tcp_header->seq); u->exp_seq = tcp_header->ack_seq; ack_seq = ntohl(tcp_header->ack_seq); if (u->last_seq == seq && u->last_ack_seq == ack_seq) { u->fast_retransmit_cnt++; if (u->fast_retransmit_cnt == 3) { fast_retransmit(u, ack_seq); return; } } else { update_ack_packets(u, ack_seq); u->fast_retransmit_cnt = 0; } u->last_ack_seq = ack_seq; u->last_seq = seq; if (cont_len > 0) { u->last_recv_resp_cont_time = tc_milliscond_time(); resp_cont_cnt++; u->state.resp_waiting = 0; u->exp_ack_seq = htonl(seq + cont_len); send_faked_ack(u); } else { u->exp_ack_seq = tcp_header->seq; } if (tcp_header->syn) { tc_log_debug1(LOG_DEBUG, 0, "recv syn from back:%u", ntohs(u->src_port)); u->exp_ack_seq = htonl(ntohl(u->exp_ack_seq) + 1); if (!u->state.resp_syn_received) { conn_cnt++; active_conn_cnt++; u->state.resp_syn_received = 1; u->state.status |= SYN_CONFIRM; tc_log_debug2(LOG_DEBUG, 0, "exp ack seq:%u, p:%u", ntohl(u->exp_ack_seq), ntohs(u->src_port)); if (size_tcp > TCP_HEADER_MIN_LEN) { retrieve_options(u, REMOTE, tcp_header); if (u->wscale > 0) { tc_log_debug2(LOG_DEBUG, 0, "wscale:%u, p:%u", u->wscale, ntohs(u->src_port)); } } process_user_packet(u); } else { tc_log_debug1(LOG_DEBUG, 0, "syn, but already syn received:%u", ntohs(u->src_port)); } } else if (tcp_header->fin) { tc_log_debug1(LOG_DEBUG, 0, "recv fin from back:%u", ntohs(u->src_port)); u->exp_ack_seq = htonl(ntohl(u->exp_ack_seq) + 1); u->state.status |= SERVER_FIN; send_faked_ack(u); process_user_packet(u); fin_recv_cnt++; } else if (tcp_header->rst) { tc_log_info(LOG_NOTICE, 0, "recv rst from back:%u", ntohs(u->src_port)); rst_recv_cnt++; if (u->state.status == SYN_SENT) { if (!u->state.over) { conn_reject_cnt++; } } u->state.over = 1; u->state.status |= SERVER_FIN; } } else { tc_log_debug_trace(LOG_DEBUG, 0, BACKEND_FLAG, ip_header, tcp_header); tc_log_debug0(LOG_DEBUG, 0, "no active session for me"); } }
static void send_packets_from_pcap(int first) { int l2_len, ip_pack_len, p_valid_flag = 0; bool stop; pcap_t *pcap; unsigned char *pkt_data, *frame, *ip_data; struct pcap_pkthdr pkt_hdr; pcap = clt_settings.pcap; if (pcap == NULL) { return; } gettimeofday(&cur_time, NULL); stop = check_read_stop(); while (!stop) { pkt_data = (u_char *) pcap_next(pcap, &pkt_hdr); if (pkt_data != NULL) { if (pkt_hdr.caplen < pkt_hdr.len) { tc_log_info(LOG_WARN, 0, "truncated packets,drop"); } else { ip_data = get_ip_data(clt_settings.pcap, pkt_data, pkt_hdr.len, &l2_len); if (l2_len < ETHERNET_HDR_LEN) { tc_log_info(LOG_WARN, 0, "l2 len is %d", l2_len); continue; } last_pack_time = pkt_hdr.ts; if (ip_data != NULL) { clt_settings.pcap_time = last_pack_time.tv_sec * 1000 + last_pack_time.tv_usec / 1000; ip_pack_len = pkt_hdr.len - l2_len; tc_log_debug2(LOG_DEBUG, 0, "frame len:%d, ip len:%d", pkt_hdr.len, ip_pack_len); frame = ip_data - ETHERNET_HDR_LEN; dispose_packet(frame, ip_pack_len + ETHERNET_HDR_LEN, ip_pack_len, &p_valid_flag); if (p_valid_flag) { tc_log_debug0(LOG_DEBUG, 0, "valid flag for packet"); if (first) { first_pack_time = pkt_hdr.ts; first = 0; } else { adj_v_pack_diff = timeval_diff(&last_v_pack_time, &last_pack_time); } /* set last valid packet time in pcap file */ last_v_pack_time = last_pack_time; stop = check_read_stop(); } else { tc_log_debug0(LOG_DEBUG, 0, "invalid flag"); } } } } else { tc_log_info(LOG_WARN, 0, "stop, null from pcap_next"); stop = true; read_pcap_over = true; read_pcap_over_time = tc_time(); } } }