예제 #1
0
/* replicate packets for multiple-copying */
static void
replicate_packs(char *packet, int length, int replica_num)
{
    int               i;
    uint16_t          orig_port, addition, dest_port, rand_port;
    uint32_t          size_ip;
    tc_tcp_header_t  *tcp_header;
    tc_ip_header_t   *ip_header;
    
    ip_header  = (tc_ip_header_t *) packet;
    size_ip    = ip_header->ihl << 2;
    tcp_header = (tc_tcp_header_t *) ((char *) ip_header + size_ip);
    rand_port  = clt_settings.rand_port_shifted;
    orig_port  = ntohs(tcp_header->source);

    tc_log_debug1(LOG_DEBUG, 0, "orig port:%u", orig_port);

    for (i = 1; i < replica_num; i++) {

        addition   = (((i << 1) - 1) << 5) + rand_port;
        dest_port  = get_appropriate_port(orig_port, addition);
        tcp_header->source = htons(dest_port);
        process_packet(true, packet, length);

        tc_log_debug2(LOG_DEBUG, 0, "new port:%u,add:%u", dest_port, addition);
    }
}
예제 #2
0
static void
replicate_packs(unsigned char *frame, int frame_len, int replica_num)
{
    int              i;
    uint32_t         size_ip;
    uint16_t         orig_port, addition, dest_port, rand_port;
    unsigned char   *packet;
    tc_ip_header_t  *ip_header;
    tc_udp_header_t *udp_header;

    packet     = frame + ETHERNET_HDR_LEN;
    ip_header  = (tc_ip_header_t *) packet;
    size_ip    = ip_header->ihl << 2;
    udp_header = (tc_udp_header_t *) ((char *) ip_header + size_ip);
    orig_port  = ntohs(udp_header->source);

    tc_log_debug1(LOG_DEBUG, 0, "orig port:%u", orig_port);

    rand_port = clt_settings.rand_port_shifted;
    for (i = 1; i < replica_num; i++) {
        addition   = (((i << 1) - 1) << 5) + rand_port;
        dest_port  = get_appropriate_port(orig_port, addition);

        tc_log_debug2(LOG_DEBUG, 0, "new port:%u,add:%u", dest_port, addition);

        udp_header->source = htons(dest_port);
        process_packet(true, frame, frame_len);
    }
}
예제 #3
0
파일: tc_socket.c 프로젝트: MistShi/tcpcopy
int
tc_socket_send(int fd, char *buffer, int len)
{
    ssize_t send_len;

    while (len > 0) {
        send_len = send(fd, (const void *) buffer, len, 0);

        if (-1 == send_len) {
            tc_log_info(LOG_ERR, errno, "fd:%d", fd);
            return TC_ERROR;
        }

        tc_log_debug2(LOG_DEBUG, 0, "send len:%d, requested len:%d", 
                send_len, len);

        if (send_len != len) {
            tc_log_info(LOG_WARN, 0, "fd:%d, send len:%ld, buffer size:%ld",
                    fd, send_len, len);
        }

        buffer += send_len;
        len -= send_len;
    }

    return TC_OK;
}
예제 #4
0
int
tc_socket_cmb_recv(int fd, int *num, char *buffer)
{
    int     read_num = 0;
    size_t  last;
    ssize_t n, len;

    last = 0;
    len = sizeof(uint16_t);

    for ( ;; ) {
        n = recv(fd, buffer + last, len, 0);

        if (n == -1) {
            if (errno == EAGAIN || errno == EINTR) {
                continue;
            } else {
                tc_log_info(LOG_NOTICE, errno, "return -1,fd:%d", fd);
                return TC_ERROR;
            }
        }

        if (n == 0) {
            tc_log_info(LOG_NOTICE, 0, "recv length 0,fd:%d", fd);
            return TC_ERROR;
        }

        last += n;

        tc_log_debug1(LOG_DEBUG, 0, "current len:%d", len);
        if ((!read_num) && last >= sizeof(uint16_t)) {
            *num = (int) ntohs(*(uint16_t *) buffer);
            if (*num > COMB_MAX_NUM) {
                tc_log_info(LOG_WARN, 0, "num:%d larger than threshold", *num);
                return TC_ERROR;
            }
            read_num = 1;
            len = ((*num) * MSG_SERVER_SIZE) + len;
            tc_log_debug2(LOG_DEBUG, 0, "all bytes needed reading:%d,num:%d",
                    len, *num);
        }

        tc_log_debug1(LOG_DEBUG, 0, "this time reading:%d", n);
        if ((len -= n) == 0) {
            tc_log_debug1(LOG_DEBUG, 0, "remain readed:%d", len);
            break;
        }

        if (len < 0) {
            tc_log_info(LOG_WARN, 0, "read:%d,num packs:%d, remain:%d",
                    n, *num, len);
            break;
        }
        tc_log_debug1(LOG_DEBUG, 0, "remain readed:%d", len);
    }

    return TC_OK;
}
예제 #5
0
static void 
update_timestamp(tc_user_t *u, tc_tcp_header_t *tcp_header)
{
    uint32_t       ts;
    unsigned int   opt, opt_len;
    unsigned char *p, *end;

    p = ((unsigned char *) tcp_header) + TCP_HEADER_MIN_LEN;
    end =  ((unsigned char *) tcp_header) + (tcp_header->doff << 2);  
    while (p < end) {
        opt = p[0];
        switch (opt) {
            case TCPOPT_TIMESTAMP:
                if ((p + 1) >= end) {
                    return;
                }
                opt_len = p[1];
                if ((p + opt_len) <= end) {
                    ts = htonl(u->ts_ec_r);
                    tc_log_debug2(LOG_DEBUG, 0, "set ts reply:%u,p:%u", 
                            u->ts_ec_r, ntohs(u->src_port));
                    bcopy((void *) &ts, (void *) (p + 6), sizeof(ts));
                    ts = EXTRACT_32BITS(p + 2);
                    if (ts < u->ts_value) {
                        tc_log_debug1(LOG_DEBUG, 0, "ts < history,p:%u",
                                ntohs(u->src_port));
                        ts = htonl(u->ts_value);
                        bcopy((void *) &ts, (void *) (p + 2), sizeof(ts));
                    } else {
                        u->ts_value = ts;
                    }
                }
                return;
            case TCPOPT_NOP:
                p = p + 1; 
                break;
            case TCPOPT_EOL:
                return;
            default:
                if ((p + 1) >= end) {
                    return;
                }
                opt_len = p[1];
                if (opt_len < 2) {
                    tc_log_info(LOG_WARN, 0, "opt len:%d", opt_len);
                    return;
                }
                p += opt_len;
                break;
        }    
    }
    return;
}
예제 #6
0
파일: manager.c 프로젝트: jbli/tcpcopy
static 
bool check_read_stop()
{
    uint64_t history_diff = timeval_diff(&first_pack_time, &last_pack_time);
    uint64_t cur_diff     = timeval_diff(&base_time, &cur_time);
    uint64_t diff;
    tc_log_debug2(LOG_DEBUG, "diff,old:%llu,new:%llu", 
            history_diff, cur_diff);
    if(history_diff <= cur_diff){
        return false;
    }
    diff = history_diff - cur_diff;
    /* More than 1 seconds */
    if(diff > 1000){
        return true;
    }
    return false;
}
예제 #7
0
파일: manager.c 프로젝트: chijiao/tcpcopy
static bool
check_read_stop()
{
    uint64_t diff, history_diff, cur_diff;

    history_diff = timeval_diff(&first_pack_time, &last_pack_time);
    cur_diff     = timeval_diff(&base_time, &cur_time);

    tc_log_debug2(LOG_DEBUG, 0, "diff,old:%llu,new:%llu",
                  history_diff, cur_diff);
    if (history_diff <= cur_diff) {
        return false;
    }

    diff = history_diff - cur_diff;
    if (diff > 0) {
        return true;
    }

    return false;
}
예제 #8
0
void 
tc_add_session(p_session_entry entry)
{
    uint32_t h = supplemental_hash((uint32_t) entry->key);
    uint32_t index = table_index(h, s_table->size);
    p_session_entry e = NULL, last = NULL;

    for(e = s_table->entries[index]; e != NULL; e = e->next) { 
        last = e;
    } 

    if (last == NULL) {
        s_table->entries[index] = entry;
    } else {
        last->next = entry;
    }

    s_table->num_of_sessions++;
    tc_log_debug2(LOG_DEBUG, 0, "index:%d,sessions in table:%d",
            index, s_table->num_of_sessions);

}
예제 #9
0
static
void process_user_packet(tc_user_t *u)
{
    unsigned char   frame[MAX_FRAME_LENGTH];

    if (send_stop(u)) {
        return;
    }

    while (true) {
        if (u->orig_frame->frame_len > MAX_FRAME_LENGTH) {
            tc_log_info(LOG_NOTICE, 0, " frame length may be damaged");
        }

        memcpy(frame, u->orig_frame->frame_data, u->orig_frame->frame_len);
        process_packet(u, frame);
        u->total_packets_sent++;
        u->orig_frame = u->orig_frame->next;


        if (send_stop(u)) {
            break;
        }
        tc_log_debug1(LOG_DEBUG, 0, "check resp waiting:%u",
                ntohs(u->src_port));
        if (!u->orig_frame->belong_to_the_same_req) {
            tc_log_debug2(LOG_DEBUG, 0, "user state:%d,port:%u",
                u->state.status, ntohs(u->src_port));
            if (u->state.status & SYN_CONFIRM) {
                tc_log_debug1(LOG_DEBUG, 0, "set resp waiting:%u",
                        ntohs(u->src_port));
                u->state.resp_waiting = 1;
            }
            break;
        } else {
            tc_log_debug1(LOG_DEBUG, 0, "the same req:%u",  ntohs(u->src_port));
        }
    }
}
예제 #10
0
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;
    }
}
예제 #11
0
bool 
tc_build_users(int port_prioritized, int num_users, uint32_t *ips, int num_ip)
{
    int       i, j, k, count, sub_key, slot_avg,
             *stat, *accum, *slot_cnt, *sub_keys;
    uint16_t *buf_ports, port;
    uint32_t  ip, *buf_ips;
    uint64_t  key, *keys;
    
    tc_log_info(LOG_INFO, 0, "enter tc_build_users");

    size_of_users = num_users;

    slot_avg = SLOT_AVG;
    if (size_of_users < slot_avg) {
        slot_avg = size_of_users;
    }

    size_of_user_index = size_of_users / slot_avg;

    user_array = (tc_user_t *) calloc (size_of_users, sizeof (tc_user_t));
    user_index_array = (tc_user_index_t *) calloc (size_of_user_index, 
            sizeof(tc_user_index_t));
    if (user_index_array == NULL || user_array == NULL) {
        tc_log_info(LOG_WARN, 0, "calloc error for users");
        return false;
    }

    count     = 0;
    keys      = (uint64_t *) malloc (sizeof(uint64_t) * size_of_users);
    sub_keys  = (int *) malloc (sizeof(int) * size_of_users);
    buf_ips   = (uint32_t *) malloc (sizeof(uint32_t) * size_of_users);
    buf_ports = (uint16_t *) malloc (sizeof(uint16_t) * size_of_users);
    accum     = (int *) malloc (sizeof(int) * size_of_users);
    stat      = (int *) malloc (sizeof(int) * size_of_user_index);
    slot_cnt  = (int *) malloc (sizeof(int) * size_of_user_index);

    if (keys == NULL || sub_keys == NULL || buf_ips == NULL || 
            buf_ports == NULL || accum == NULL || stat == NULL 
            || slot_cnt == NULL) 
    {
        free(keys);
        free(sub_keys);
        free(buf_ips);
        free(buf_ports);
        free(accum);
        free(stat);
        free(slot_cnt);
        tc_log_info(LOG_WARN, 0, "calloc error for building users");
        return false;
    }

    memset(stat, 0 ,sizeof(int) * size_of_user_index);
    memset(slot_cnt, 0 ,sizeof(int) * size_of_user_index);
    memset(sub_keys, 0, sizeof(int) * size_of_users);

    if (port_prioritized) {
        for ( i = 0; i < num_ip; i++) {
            ip = ips[i];
            for (j = FIRST_PORT; j <= LAST_PORT; j++) {
                port = get_port(j);
                key = tc_get_key(ip, port);
                if (count >= size_of_users) {
                    break;
                }

                sub_key = key % size_of_user_index;
                if (stat[sub_key] >= SLOT_MAX) {
                    continue;
                }
                buf_ips[count] = ip;
                buf_ports[count] = port;
                sub_keys[count] = sub_key;
                keys[count++] = key;
                stat[sub_key]++;
            }
        }
    } else {
        for (j = FIRST_PORT; j <= LAST_PORT; j++) {
            port = get_port(j);
            for ( i = 0; i < num_ip; i++) {
                ip = ips[i];

                key = tc_get_key(ip, port);
                if (count >= size_of_users) {
                    break;
                }

                sub_key = key % size_of_user_index;
                if (stat[sub_key] >= SLOT_MAX) {
                    continue;
                }
                buf_ips[count] = ip;
                buf_ports[count] = port;
                sub_keys[count] = sub_key;
                keys[count++] = key;
                stat[sub_key]++;
            }
        }
    }

    if (count < size_of_users) {
        tc_log_info(LOG_WARN, 0, "insuffient ips:%d for creating users:%d", 
                num_ip, size_of_users);
        tc_log_info(LOG_NOTICE, 0, "change users from %d to %d", 
                size_of_users, count); 
        size_of_users = count;
        size_of_user_index = size_of_users / slot_avg;
    }

    user_index_array[0].index = 0;
    for ( i = 1; i < size_of_user_index; i++) {
        user_index_array[i].index = stat[i - 1] + user_index_array[i - 1].index;
    }

    for ( i = 0; i < size_of_users; i++) {
        sub_key = sub_keys[i];
        if (sub_key > 0) {
            accum[i] = user_index_array[sub_key].index  + slot_cnt[sub_key];
        } else {
            accum[i] = slot_cnt[sub_key];

        }

        k = accum[i];
        user_array[k].src_addr = buf_ips[i];
        user_array[k].src_port = buf_ports[i];
        user_array[k].key = keys[i];
        tc_log_debug2(LOG_DEBUG, 0, "usr key :%llu,pos=%d", keys[i], k);

        slot_cnt[sub_key]++;
    }

    free(sub_keys);
    free(buf_ports);
    free(buf_ips);
    free(accum);
    free(stat);
    free(keys);
    free(slot_cnt);

    tc_init_session_for_users();

    tc_log_info(LOG_INFO, 0, "leave tc_build_users");

    return true;
}
예제 #12
0
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");
    }

}
예제 #13
0
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 || read_pcap_over) {
        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;
        }
    }
}
static int 
prepare_for_renew_session(tc_sess_t *s, tc_iph_t *ip, tc_tcph_t *tcp)
{
    uint16_t            size_ip;
    uint32_t            tot_clen, base_seq;
    tc_iph_t           *fir_ip, *t_ip;
    tc_tcph_t          *fir_tcp, *t_tcp;
    p_link_node         ln;
    unsigned char      *p;
    mysql_table_item_t *item;
    tc_mysql_session   *mysql_sess;

    if (!ctx.fir_auth_pack) {
        tc_log_info(LOG_WARN, 0, "no first auth pack here");
        return TC_ERR;
    }

    mysql_sess = s->data;
    if (mysql_sess == NULL) {
        tc_log_info(LOG_WARN, 0, "mysql session structure is not allocated");
        return TC_ERR;
    } else if (mysql_sess->fir_auth_added) {
        tc_log_info(LOG_NOTICE, 0, "dup visit prepare_for_renew_session");
        return TC_OK;
    }

    s->sm.need_rep_greet = 1;

    fir_ip        = ctx.fir_auth_pack;
    fir_ip->saddr = ip->saddr;
    size_ip       = fir_ip->ihl << 2;
    fir_tcp = (tc_tcph_t *) ((char *) fir_ip + size_ip);
    fir_tcp->source = tcp->source;

    tot_clen = ctx.fir_auth_cont_len;

    item = hash_find(ctx.table, s->hash_key);
    if (item) {
        tot_clen += item->tot_cont_len;
    }

    tc_log_debug2(LOG_INFO, 0, "total len subtracted:%u,p:%u", tot_clen, 
            ntohs(s->src_port));

    tcp->seq     = htonl(ntohl(tcp->seq) - tot_clen);
    fir_tcp->seq = htonl(ntohl(tcp->seq) + 1);
    tc_save_pack(s, s->slide_win_packs, fir_ip, fir_tcp);  
    mysql_sess->fir_auth_added = 1;

    base_seq = ntohl(fir_tcp->seq) + ctx.fir_auth_cont_len;

    if (item) {
        ln = link_list_first(item->list); 
        while (ln) {
            p = (unsigned char *) ln->data;
            t_ip  = (tc_iph_t *) (p + ETHERNET_HDR_LEN);
            t_tcp = (tc_tcph_t *) ((char *) t_ip + size_ip);
            t_tcp->seq = htonl(base_seq);
            tc_save_pack(s, s->slide_win_packs, t_ip, t_tcp);  
            base_seq += TCP_PAYLOAD_LENGTH(t_ip, t_tcp);
            ln = link_list_get_next(item->list, ln);
        }
    }

    mysql_sess->old_ps_cleaned = 0;

    return TC_OK;
}