예제 #1
0
static int 
tc_msg_event_process(tc_event_t *rev)
{
    msg_client_t msg;

    if (tc_socket_recv(rev->fd, (char *) &msg, MSG_CLIENT_SIZE) == TC_ERROR) {
        tc_socket_close(rev->fd);
        tc_log_info(LOG_NOTICE, 0, "close sock:%d", rev->fd);
        tc_event_del(rev->loop, rev, TC_EVENT_READ);
        return TC_ERROR;
    }

    switch (msg.type) {
        case CLIENT_ADD:
            tc_log_debug1(LOG_DEBUG, 0, "add client router:%u",
                          ntohs(msg.client_port));
            router_add(msg.client_ip, msg.client_port, rev->fd);
            break;
        case CLIENT_DEL:
            tc_log_debug1(LOG_DEBUG, 0, "del client router:%u",
                          ntohs(msg.client_port));
            router_del(msg.client_ip, msg.client_port);
            break;
    }

    return TC_OK;
}
예제 #2
0
파일: interception.c 프로젝트: jbli/tcpcopy
static void interception_process(int fd)
{
    int                    diff, new_fd, i, pass_through_flag = 0;
    time_t                 now;
    unsigned long          packet_id;
    struct iphdr           *ip_header;
    struct msg_client_s    *c_msg;

    if(fd == msg_listen_sock){
        new_fd = accept(msg_listen_sock, NULL, NULL);   
        set_sock_no_delay(new_fd);
        if(new_fd != -1){
            select_server_add(new_fd);
        }
    }else if(fd == firewall_sock){
        packet_id = 0;
        ip_header = nl_firewall_recv(firewall_sock, &packet_id);
        if(ip_header != NULL){
            /* Check if it is the valid user to pass through firewall */
            for(i = 0; i < srv_settings.passed_ips.num; i++){
                if(srv_settings.passed_ips.ips[i] == ip_header->daddr){
                    pass_through_flag = 1;
                    break;
                }
            }
            if(pass_through_flag){
                /* Pass through the firewall */
                dispose_netlink_packet(NF_ACCEPT, packet_id);   
            }else{
                router_update(ip_header);
                now  = time(0);
                diff = now - last_clean_time;
                if(diff > CHECK_INTERVAL){
                    route_delete_obsolete(now);
                    delay_table_delete_obsolete(now);
                    last_clean_time = now;
                }
                 /* Drop the packet */
                dispose_netlink_packet(NF_DROP, packet_id);     
            }
        }
    }else{
        c_msg = msg_server_recv(fd);
        if(c_msg){
            if(c_msg->type == CLIENT_ADD){
                tc_log_debug1(LOG_NOTICE, "add client router:%u", 
                        ntohs(c_msg->client_port));
                router_add(c_msg->client_ip, c_msg->client_port, fd);
            }else if(c_msg->type == CLIENT_DEL){
                tc_log_debug1(LOG_NOTICE, "del client router:%u", 
                        ntohs(c_msg->client_port));
                router_del(c_msg->client_ip, c_msg->client_port);
            }
        }else{
            close(fd);
            select_server_del(fd);
            log_info(LOG_NOTICE, "close sock:%d", fd);
        }
    }
}
예제 #3
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;
}
예제 #4
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);
    }
}
예제 #5
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);
    }
}
static bool 
check_pack_needed_for_recons(tc_sess_t *s, tc_iph_t *ip, tc_tcph_t *tcp)
{
    uint16_t            size_tcp;
    p_link_node         ln;
    unsigned char      *payload, command, *pkt;
    mysql_table_item_t *item;

    if (s->cur_pack.cont_len > 0) {

        size_tcp = tcp->doff << 2;
        payload = (unsigned char *) ((char *) tcp + size_tcp);
        /* skip packet length */
        payload  = payload + 3;
        /* skip packet number */
        payload  = payload + 1;
        command  = payload[0];

        if (command != COM_STMT_PREPARE) {
            return false;
        }

        item = hash_find(ctx.table, s->hash_key);
        if (!item) {
            item = tc_pcalloc(ctx.pool, sizeof(mysql_table_item_t));
            if (item != NULL) {
                item->list = link_list_create(ctx.pool);
                if (item->list != NULL) {
                    hash_add(ctx.table, ctx.pool, s->hash_key, item);
                    if (ctx.table->total > MAX_TABLE_ITEM_NUM) {
                        tc_log_info(LOG_INFO, 0, "too many items in ctx.table");
                    }
                } else {
                    tc_log_info(LOG_ERR, 0, "list create err");
                    return false;
                }
            } else {
                tc_log_info(LOG_ERR, 0, "mysql item create err");
                return false;
            }
        }

        if (item->list->size > MAX_SP_SIZE) {
            tc_log_info(LOG_INFO, 0, "too many prepared stmts for a session");
            return false;
        }

        tc_log_debug1(LOG_INFO, 0, "push packet:%u", ntohs(s->src_port));

        pkt = (unsigned char *) cp_fr_ip_pack(ctx.pool, ip);
        ln  = link_node_malloc(ctx.pool, pkt);
        ln->key = ntohl(tcp->seq);
        link_list_append_by_order(item->list, ln);
        item->tot_cont_len += s->cur_pack.cont_len;

        return true;
    }

    return false;
}
예제 #7
0
static void
update_ack_packets(tc_user_t *u, uint32_t cur_ack_seq)
{
    frame_t          *unack_frame, *next;

    unack_frame = u->orig_unack_frame;
    if (unack_frame == NULL) {
        return;
    }

    next = unack_frame->next;
    while (true) {
        if (unack_frame == u->orig_frame) {
            break;
        }
        if (next != NULL) {
            if (next->seq == cur_ack_seq) {
                u->orig_unack_frame = unack_frame->next;
                break;
            } else if (before(cur_ack_seq, next->seq) && 
                    before(unack_frame->seq, cur_ack_seq)) 
            {
                tc_log_debug1(LOG_DEBUG, 0, "partially acked:%u", 
                        ntohs(u->src_port));
                break;
            } else {    
                tc_log_debug1(LOG_DEBUG, 0, "skipped:%u", 
                        ntohs(u->src_port));
                unack_frame = next;
                next = unack_frame->next;
                if (unack_frame == u->orig_session->last_frame) {
                    break;
                }
            }
        } else {
            if (before(unack_frame->seq, cur_ack_seq)) {
                unack_frame = unack_frame->next;
            }
            u->orig_unack_frame = unack_frame;
            break;
        }
    }

}
예제 #8
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;
}
예제 #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 void
fast_retransmit(tc_user_t *u, uint32_t cur_ack_seq)
{
    frame_t          *unack_frame, *next;

    unack_frame = u->orig_unack_frame;
    if (unack_frame == NULL) {
        return;
    }

    next = unack_frame->next;
    while (true) {
        if (unack_frame == u->orig_frame) {
            break;
        }
        if (unack_frame->seq == cur_ack_seq) {
            tc_log_debug1(LOG_DEBUG, 0, "packets retransmitted:%u", 
                    ntohs(u->src_port));
            process_packet(u, unack_frame->frame_data);
            break;
        } else if (before(unack_frame->seq, cur_ack_seq) && next != NULL &&
                before(cur_ack_seq, next->seq)) 
        {
            process_packet(u, unack_frame->frame_data);
            break;
        } else if (before(unack_frame->seq, cur_ack_seq)) {
            unack_frame = next;
            if (unack_frame == NULL) {
                break;
            }
            next = unack_frame->next;
        } else {
            tc_log_debug1(LOG_DEBUG, 0, "packets retransmitted not match:%u", 
                    ntohs(u->src_port));
            break;
        }
    }
}
예제 #11
0
int
tc_raw_socket_send(int fd, void *buf, size_t len, uint32_t ip)
{
    ssize_t             send_len, offset = 0, num_bytes;
    const char         *ptr;
    struct sockaddr_in  dst_addr;

    if (fd > 0) {

        memset(&dst_addr, 0, sizeof(struct sockaddr_in));

        dst_addr.sin_family = AF_INET;
        dst_addr.sin_addr.s_addr = ip;

        ptr = buf;

        /*
         * The output packet will take a special path of IP layer
         * (raw_sendmsg->raw_send_hdrinc->NF_INET_LOCAL_OUT->...).
         * No IP fragmentation will take place if needed. 
         * This means that a raw packet larger than the MTU of the 
         * interface will probably be discarded. Instead ip_local_error(), 
         * which does general sk_buff cleaning, is called and an 
         * error EMSGSIZE is returned. 
         */
        do {
            num_bytes = len - offset;
            send_len = sendto(fd, ptr + offset, num_bytes, 0, 
                    (struct sockaddr *) &dst_addr, sizeof(dst_addr));

            if (send_len == -1) {
                if (errno == EINTR) {
                    tc_log_info(LOG_NOTICE, errno, "raw fd:%d EINTR", fd);
                } else if (errno == EAGAIN) {
                    tc_log_debug1(LOG_NOTICE, errno, "raw fd:%d EAGAIN", fd);
                } else {
                    tc_log_info(LOG_ERR, errno, "raw fd:%d", fd);
                    tc_socket_close(fd);
                    return TC_ERROR;
                }   

            }  else {
                offset += send_len;
            }   
        } while (offset < len);
    }

    return TC_OK;
}
예제 #12
0
int
tc_socket_send(int fd, char *buffer, int len)
{
    int         cnt = 0;
    ssize_t     send_len, offset = 0, num_bytes;
    const char *ptr;

    if (len <= 0) {
        return TC_OK;
    }

    ptr = buffer;
    num_bytes = len - offset;

    do {

        send_len = send(fd, ptr + offset, num_bytes, 0);

        if (send_len == -1) {

            if (cnt > MAX_RW_TRIES) {
                tc_log_info(LOG_ERR, 0, "send timeout,fd:%d", fd);
                return TC_ERROR;
            }
            if (errno == EINTR) {
                tc_log_info(LOG_NOTICE, errno, "fd:%d EINTR", fd);
                cnt++;
            } else if (errno == EAGAIN) {
                tc_log_debug1(LOG_NOTICE, errno, "fd:%d EAGAIN", fd);
                cnt++;
            } else {
                tc_log_info(LOG_ERR, errno, "fd:%d", fd);
                return TC_ERROR;
            }
        } else {

            if (send_len != num_bytes) {
                tc_log_info(LOG_WARN, 0, "fd:%d, slen:%ld, bsize:%ld",
                        fd, send_len, num_bytes);
            }

            offset += send_len;
            num_bytes -= send_len;
        }
    } while (offset < len);

    return TC_OK;
}
예제 #13
0
void
tc_event_expire_timers(void)
{
    tc_event_timer_t  *ev;
    tc_rbtree_node_t  *node, *root, *sentinel;

    sentinel = tc_event_timer_rbtree.sentinel;

    for ( ;; ) {

        root = tc_event_timer_rbtree.root;

        if (root == sentinel) {
            return;
        }

        node = tc_rbtree_min(root, sentinel);

        /* node->key <= tc_current_time */

        if ((tc_msec_int_t) (node->key - tc_current_time_msec) <= 0) {
            ev = (tc_event_timer_t *) ((char *) node -
                    offsetof(tc_event_timer_t, timer));

#if (TC_DEBUG)
            tc_log_debug1(LOG_DEBUG, 0, "del timer:%llu", ev);
#endif
            tc_rbtree_delete(&tc_event_timer_rbtree, &ev->timer);

            ev->timer_set = 0;

            ev->handler(ev);

            continue;
        }

        break;
    }

}
예제 #14
0
tc_event_timer_t* 
tc_event_add_timer(tc_pool_t *pool, tc_msec_t timer, void *data, 
        tc_event_timer_handler_pt handler)
{
    tc_msec_t         key;
    tc_event_timer_t *ev;

    ev = (tc_event_timer_t *) tc_palloc(pool, sizeof(tc_event_timer_t));
    if (ev != NULL) {
        ev->pool = pool;
        ev->handler = handler;
        ev->data = data;
        key = ((tc_msec_t) tc_current_time_msec) + timer;
        ev->timer.key = key;

        tc_rbtree_insert(&tc_event_timer_rbtree, &ev->timer);

        tc_log_debug1(LOG_DEBUG, 0, "add timer:%llu", ev);
        ev->timer_set = 1;
    }
    return ev;
}
static bool
check_renew_session(tc_iph_t *ip, tc_tcph_t *tcp)
{
    uint16_t        size_ip, size_tcp, tot_len, cont_len;
    unsigned char  *payload, command, pack_number;

    if (ctx.fir_auth_pack == NULL) {
        tc_log_debug0(LOG_DEBUG, 0, "fir auth packet is null");
        return false;
    }

    size_ip  = ip->ihl << 2;
    size_tcp = tcp->doff << 2;
    tot_len  = ntohs(ip->tot_len);
    cont_len = tot_len - size_tcp - size_ip;

    if (cont_len > 0) {
        payload = (unsigned char *) ((char *) tcp + size_tcp);
        /* skip packet length */
        payload = payload + 3;
        /* retrieve packet number */
        pack_number = payload[0];
        /* if it is the second authenticate_user, skip it */
        if (pack_number != 0) {
            return false;
        }
        /* skip packet number */
        payload = payload + 1;

        command = payload[0];
        tc_log_debug1(LOG_DEBUG, 0, "mysql command:%u", command);
        if (command == COM_QUERY || command == COM_STMT_EXECUTE) {
            return true;
        }
    }

    return false;
}
예제 #16
0
static int
dispose_packet(char *recv_buf, int recv_len, int *p_valid_flag)
{
    int              replica_num, i, last, packet_num, max_payload,
                     index, payload_len;
    char            *packet, tmp_buf[RECV_BUF_SIZE];
    bool             packet_valid = false;
    uint16_t         id, size_ip, size_tcp, tot_len, cont_len, 
                     pack_len = 0, head_len;
    uint32_t         seq;
    tc_ip_header_t  *ip_header;
    tc_tcp_header_t *tcp_header;

    packet = recv_buf;

    if (is_packet_needed((const char *) packet)) {

        replica_num = clt_settings.replica_num;
        packet_num = 1;
        ip_header   = (tc_ip_header_t *)packet;

        if (localhost == ip_header->saddr) {
            if (clt_settings.lo_tf_ip != 0) {
                ip_header->saddr = clt_settings.lo_tf_ip;
            }
        }

        /* 
         * If the packet length is larger than MTU, we split it. 
         * This is to solve the ip fragmentation problem
         */
        if (recv_len > clt_settings.mtu) {

            /* calculate number of packets */
            size_ip     = ip_header->ihl << 2;
            tot_len     = ntohs(ip_header -> tot_len);
            if (tot_len != recv_len) {
                tc_log_info(LOG_WARN, 0, "packet len:%u, recv len:%u",
                            tot_len, recv_len);
                return TC_ERROR;
            }

            tcp_header  = (tc_tcp_header_t *) ((char *) ip_header + size_ip);
            size_tcp    = tcp_header->doff << 2;
            cont_len    = tot_len - size_tcp - size_ip;
            head_len    = size_ip + size_tcp;
            max_payload = clt_settings.mtu - head_len;
            packet_num  = (cont_len + max_payload - 1)/max_payload;
            seq         = ntohl(tcp_header->seq);
            last        = packet_num - 1;
            id          = ip_header->id;

#if (TCPCOPY_DEBUG)
            tc_log_trace(LOG_NOTICE, 0, CLIENT_FLAG, ip_header, tcp_header);
#endif
            tc_log_debug1(LOG_DEBUG, 0, "recv:%d, more than MTU", recv_len);
            index = head_len;

            for (i = 0 ; i < packet_num; i++) {
                tcp_header->seq = htonl(seq + i * max_payload);
                if (i != last) {
                    pack_len  = clt_settings.mtu;
                } else {
                    pack_len += (cont_len - packet_num * max_payload);
                }
                payload_len = pack_len - head_len;
                ip_header->tot_len = htons(pack_len);
                ip_header->id = id++;
                /* copy header here */
                memcpy(tmp_buf, recv_buf, head_len);
                /* copy payload here */
                memcpy(tmp_buf + head_len, recv_buf + index, payload_len);
                index = index + payload_len;
                if (replica_num > 1) {
                    packet_valid = process_packet(true, tmp_buf, pack_len);
                    replicate_packs(tmp_buf, pack_len, replica_num);
                } else {
                    packet_valid = process_packet(false, tmp_buf, pack_len);
                }
            }
        } else {

            if (replica_num > 1) {

                packet_valid = process_packet(true, packet, recv_len);
                replicate_packs(packet, recv_len, replica_num);
            } else {

                packet_valid = process_packet(false, packet, recv_len);
            }
        }
    }

    if (p_valid_flag) {
        *p_valid_flag = (packet_valid == true ? 1 : 0);
    }

    return TC_OK;
}
예제 #17
0
static int
tc_process_server_msg(tc_event_t *rev)
{
#if (TCPCOPY_DR)
    int            i, j;
    connections_t *connections;
#endif
#if (!TCPCOPY_COMBINED)
    int            len;
    msg_server_t   msg;
#else
    int            num, k;
    unsigned char *p, aggr_resp[COMB_LENGTH + sizeof(uint16_t)];
#endif

#if (!TCPCOPY_COMBINED)
    len = MSG_SERVER_SIZE;
#endif

#if (!TCPCOPY_COMBINED)
    if (tc_socket_recv(rev->fd, (char *) &msg, len) == TC_ERROR)
#else
    if (tc_socket_cmb_recv(rev->fd, &num, (char *) aggr_resp) == TC_ERROR)
#endif
    {
        tc_log_info(LOG_ERR, 0, "Recv socket(%d)error", rev->fd);
        tc_log_info(LOG_ERR, 0, "server may be closed or");
        tc_log_info(LOG_ERR, 0, "backend TCP/IP kernel memeory is too low or");
        tc_log_info(LOG_ERR, 0, 
                "the version of intercept may not be equal to the version of tcpcopy");
#if (TCPCOPY_DR)

        for (i = 0; i < clt_settings.real_servers.num; i++) {

            connections = &(clt_settings.real_servers.connections[i]);
            for (j = 0; j < connections->num; j++) {
                if (connections->fds[j] == rev->fd) {
                    tc_socket_close(rev->fd);
                    tc_log_info(LOG_NOTICE, 0, "close sock:%d", rev->fd);
                    tc_event_del(rev->loop, rev, TC_EVENT_READ);
                    connections->num--;

                    if (connections->num == 0 && 
                            clt_settings.real_servers.active[i]) 
                    {
                        clt_settings.real_servers.active[i] = 0;
                        clt_settings.real_servers.active_num--;
                    }

                    break;
                }
            }
        }


        if (clt_settings.real_servers.active_num == 0) {
            return TC_ERR_EXIT;
        } else {
            return TC_OK;
        }
#else 
        return TC_ERR_EXIT;
#endif
    }

#if (!TCPCOPY_COMBINED)
    process_out((unsigned char *) &msg);
#else
    tc_log_debug1(LOG_DEBUG, 0, "resp packets:%d", num);
    p = aggr_resp + sizeof(uint16_t);
    for (k = 0; k < num; k++) {
        process_out(p);
        p = p + MSG_SERVER_SIZE;
    }
#endif

    return TC_OK;
}
예제 #18
0
static int
dispose_packet(unsigned char *frame, int frame_len, int ip_recv_len,
               int *p_valid_flag)
{
    int              replica_num, i, last, packet_num, max_payload,
                     index, payload_len;
    char             *p, buf[ETHERNET_HDR_LEN + IP_RECV_BUF_SIZE];
    bool             packet_valid = false;
    uint16_t         id, size_ip, size_tcp, tot_len, cont_len,
                     pack_len = 0, head_len;
    uint32_t         seq;
    unsigned char   *packet;
    tc_ip_header_t  *ip_header;
    tc_tcp_header_t *tcp_header;

    packet = frame + ETHERNET_HDR_LEN;

    if (is_packet_needed(packet)) {

        replica_num = clt_settings.replica_num;
        ip_header   = (tc_ip_header_t *) packet;

        if (clt_settings.clt_tf_ip != 0) {
            ip_header->saddr = clt_settings.clt_tf_ip;
        }

        /*
         * If the packet length is larger than MTU, we split it.
         */
        if (ip_recv_len > clt_settings.mtu) {

            /* calculate number of packets */
            size_ip     = ip_header->ihl << 2;
            tot_len     = ntohs(ip_header -> tot_len);
            if (tot_len != ip_recv_len) {
                tc_log_info(LOG_WARN, 0, "packet len:%u, recv len:%u",
                            tot_len, ip_recv_len);
                return TC_ERROR;
            }

            tcp_header  = (tc_tcp_header_t *) ((char *) ip_header + size_ip);
            size_tcp    = tcp_header->doff << 2;
            cont_len    = tot_len - size_tcp - size_ip;
            head_len    = size_ip + size_tcp;
            max_payload = clt_settings.mtu - head_len;
            packet_num  = (cont_len + max_payload - 1)/max_payload;
            seq         = ntohl(tcp_header->seq);
            last        = packet_num - 1;
            id          = ip_header->id;

#if (TCPCOPY_DEBUG)
            tc_log_trace(LOG_NOTICE, 0, CLIENT_FLAG, ip_header, tcp_header);
#endif
            tc_log_debug1(LOG_DEBUG, 0, "recv:%d, more than MTU", ip_recv_len);
            index = head_len;

            for (i = 0 ; i < packet_num; i++) {
                tcp_header->seq = htonl(seq + i * max_payload);
                if (i != last) {
                    pack_len  = clt_settings.mtu;
                } else {
                    pack_len += (cont_len - packet_num * max_payload);
                }
                payload_len = pack_len - head_len;
                ip_header->tot_len = htons(pack_len);
                ip_header->id = id++;
                p = buf + ETHERNET_HDR_LEN;
                /* copy header here */
                memcpy(p, (char *) packet, head_len);
                p +=  head_len;
                /* copy payload here */
                memcpy(p, (char *) (packet + index), payload_len);
                index = index + payload_len;
                if (replica_num > 1) {
                    packet_valid = process_packet(true, (unsigned char *) buf,
                                                  ETHERNET_HDR_LEN + pack_len);
                    replicate_packs((unsigned char *) buf,
                                    ETHERNET_HDR_LEN + pack_len, replica_num);
                } else {
                    packet_valid = process_packet(false, (unsigned char *) buf,
                                                  ETHERNET_HDR_LEN + pack_len);
                }
            }
        } else {

            if (replica_num > 1) {

                packet_valid = process_packet(true, frame, frame_len);
                replicate_packs(frame, frame_len, replica_num);
            } else {

                packet_valid = process_packet(false, frame, frame_len);
            }
        }
    }

    if (p_valid_flag) {
        *p_valid_flag = (packet_valid == true ? 1 : 0);
    }

    return TC_OK;
}
예제 #19
0
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;
}
예제 #20
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");
    }

}
예제 #21
0
static int 
tc_msg_event_proc(tc_event_t *rev)
{
    msg_clt_t       msg;
    register int    fd, version;
    tunnel_basic_t *tunnel;

    fd = rev->fd;
    tunnel = srv_settings.tunnel;

    if (!tunnel[fd].first_in) {
        if (tc_socket_rcv(fd, (char *) &msg, tunnel[fd].clt_msg_size) == TC_ERR)
        {
            tc_intercept_release_tunnel(fd, rev);
            return TC_ERR;
        }
    } else {

        if (tc_socket_rcv(fd, (char *) &msg, MSG_CLT_MIN_SIZE) != TC_ERR) {
            tunnel[fd].first_in = 0;

            version = ntohs(msg.type);
            if (msg.clt_ip != 0 || msg.clt_port != 0) {
                tc_log_info(LOG_ERR, 0, "client too old for intercept");
                return TC_ERR;
            } else {
                if (version != INTERNAL_VERSION) {
                    tc_log_info(LOG_WARN, 0, 
                            "not compatible,client:%d,intercept:%d",
                            msg.type, INTERNAL_VERSION);
                }
                tunnel[fd].clt_msg_size = MSG_CLT_SIZE;
                if (tc_socket_rcv(fd, ((char *) &msg + MSG_CLT_MIN_SIZE), 
                            MSG_CLT_SIZE - MSG_CLT_MIN_SIZE) == TC_ERR)
                {
                    tc_intercept_release_tunnel(fd, rev);
                    return TC_ERR;
                }
                return TC_OK;
            }
        } else {
            tc_intercept_release_tunnel(fd, rev);
            return TC_ERR;
        }
    }

    msg.clt_ip = msg.clt_ip;
    msg.clt_port = msg.clt_port;
    msg.type = ntohs(msg.type);
    msg.target_ip = msg.target_ip;
    msg.target_port = msg.target_port;

    switch (msg.type) {
        case CLIENT_ADD:
#if (!TC_SINGLE)
            tot_router_items++;
            tc_log_debug1(LOG_DEBUG, 0, "add client router:%u",
                    ntohs(msg.clt_port));
            router_add(msg.clt_ip, msg.clt_port, 
                    msg.target_ip,  msg.target_port, rev->fd);
#endif
            break;
        case CLIENT_DEL:
            tc_log_debug1(LOG_DEBUG, 0, "del client router:%u",
                    ntohs(msg.clt_port));
            break;
        default:
            tc_log_info(LOG_WARN, 0, "unknown msg type:%u", msg.type);
    }

    return TC_OK;
}
예제 #22
0
static int 
tc_msg_event_process(tc_event_t *rev)
{
    int          fd, version;
    msg_client_t msg;

    fd = rev->fd;

    memset(&msg, 0, sizeof(msg_client_t));

    if (tunnel[fd].first_in) {
        if (tc_socket_recv(fd, (char *) &msg, MSG_CLIENT_MIN_SIZE) == 
                TC_ERROR) 
        {
            tc_intercept_close_fd(fd, rev);
            return TC_ERROR;
        }

       version = ntohs(msg.type);

        tunnel[fd].first_in = 0;
        if (msg.client_ip != 0 || msg.client_port != 0) {
            tunnel[fd].clt_msg_size = MSG_CLIENT_MIN_SIZE;
            tc_log_info(LOG_WARN, 0, "too old tcpcopy for intercept");
            srv_settings.old = 1;
        } else {
            if (version != INTERNAL_VERSION) {
                tc_log_info(LOG_WARN, 0, 
                        "not compatible,tcpcopy:%d,intercept:%d",
                        msg.type, INTERNAL_VERSION);
            }
            tunnel[fd].clt_msg_size = MSG_CLIENT_SIZE;
            if (tc_socket_recv(fd, ((char *) &msg + MSG_CLIENT_MIN_SIZE), 
                        MSG_CLIENT_SIZE - MSG_CLIENT_MIN_SIZE) == TC_ERROR) 
            {
                tc_intercept_close_fd(fd, rev);
                return TC_ERROR;
            }
            return TC_OK;
        }

    } else {
        if (tc_socket_recv(fd, (char *) &msg, tunnel[fd].clt_msg_size) == 
                TC_ERROR) 
        {
            tc_intercept_close_fd(fd, rev);
            return TC_ERROR;
        }
    }

    msg.client_ip = msg.client_ip;
    msg.client_port = msg.client_port;
    msg.type = ntohs(msg.type);
    msg.target_ip = msg.target_ip;
    msg.target_port = msg.target_port;

    switch (msg.type) {
        case CLIENT_ADD:
#if (!TCPCOPY_SINGLE)
            tot_router_items++;
            tc_log_debug1(LOG_DEBUG, 0, "add client router:%u",
                          ntohs(msg.client_port));
            router_add(srv_settings.old, msg.client_ip, msg.client_port, 
                    msg.target_ip, msg.target_port, fd);
#endif
            break;
        case CLIENT_DEL:
            tc_log_debug1(LOG_DEBUG, 0, "del client router:%u",
                          ntohs(msg.client_port));
            break;
        default:
            tc_log_info(LOG_WARN, 0, "unknown msg type:%u", msg.type);
    }

    return TC_OK;
}
예제 #23
0
void
buffer_and_send(int mfd, int fd, msg_server_t *msg)
{
    int                  ret = TC_OK, is_send = 0, bytes;
    unsigned char       *p;
    aggregation_t       *aggr;

#if (TCPCOPY_SINGLE)
    if (mfd == 0) {
        return;
    }
#endif

    if (fd > max_fd) {
        max_fd = fd;
    }

    if (max_fd > MAX_FD_VALUE) {
        tc_log_info(LOG_WARN, 0, "fd is too large:%d", max_fd);
        max_fd = MAX_FD_VALUE;
        return;
    }

    if (!fd_valid[fd]) {
        tc_log_debug1(LOG_DEBUG, 0, "fd is not valid:%d", fd);
        return;
    }

    aggr = combined[fd];
    if (!aggr) {
        aggr = (aggregation_t *) malloc(sizeof(aggregation_t));
        if (aggr == NULL) {
            tc_log_info(LOG_ERR, errno, "can't malloc memory");
        } else {
            tc_log_info(LOG_INFO, 0, "malloc memory for fd:%d", fd);
            memset(aggr, 0, sizeof(aggregation_t));
            aggr->cur_write = aggr->aggr_resp;
            combined[fd] = aggr;
        }
    }

    if (aggr) {
        if (msg != NULL) {
            p = aggr->cur_write;
            memcpy((char *) p, (char *) msg, MSG_SERVER_SIZE); 
            aggr->cur_write = p + MSG_SERVER_SIZE;
            aggr->num = aggr->num + 1;
        } else {
            if (aggr->num == 0) {
                tc_log_debug0(LOG_DEBUG, 0, "combined num is zero");
                return;
            }
        }

        if (aggr->num == COMB_MAX_NUM) {
            is_send = 1;
        } else if (aggr->access_time < tc_current_time_sec) {
            is_send = 1;
        } else if (aggr->access_time == tc_current_time_sec) {
            if (aggr->access_msec != tc_current_time_msec) {
                is_send = 1;
            }
        }

        if (is_send) {
            tc_log_debug1(LOG_DEBUG, 0, "combined send:%d", aggr->num);
            aggr->num = htons(aggr->num);
            p = (unsigned char *) (&(aggr->num));
            bytes = aggr->cur_write - aggr->aggr_resp + sizeof(aggr->num);
            tc_log_debug1(LOG_DEBUG, 0, "send bytes:%d", bytes);
#if (!TCPCOPY_SINGLE)
            ret = tc_socket_send(fd, (char *) p, bytes);
#else
            ret = tc_socket_send(mfd, (char *) p, bytes);
#endif
            aggr->num = 0;
            aggr->cur_write = aggr->aggr_resp;
        } 

        aggr->access_time = tc_current_time_sec;
        aggr->access_msec = tc_current_time_msec;

        if (ret == TC_ERROR) {
            fd_valid[fd] = false;
            free(combined[fd]);
            combined[fd] = NULL;
        }
    }
}
예제 #24
0
void
buffer_and_send(int fd, msg_server_t *msg)
{
    int                ret = TC_OK, is_send = 0, bytes;
    unsigned char     *p;
    aggregation_t     *aggr;

    if (fd > srv_settings.max_fd) {
        srv_settings.max_fd = fd;
    }

    if (srv_settings.max_fd > MAX_FD_VALUE) {
        tc_log_info(LOG_WARN, 0, "fd is too large:%d", srv_settings.max_fd);
        srv_settings.max_fd = MAX_FD_VALUE;
        return;
    }

    if (!srv_settings.tunnel[fd].fd_valid) {
        tc_log_debug1(LOG_DEBUG, 0, "fd is not valid:%d", fd);
        return;
    }

    aggr = srv_settings.tunnel[fd].combined;
    if (!aggr) {
        aggr = (aggregation_t *) malloc(sizeof(aggregation_t));
        if (aggr == NULL) {
            tc_log_info(LOG_ERR, errno, "can't malloc memory");
        } else {
            tc_log_info(LOG_INFO, 0, "malloc memory for fd:%d", fd);
            memset(aggr, 0, sizeof(aggregation_t));
            aggr->cur_write = aggr->aggr_resp;
            srv_settings.tunnel[fd].combined = aggr;
        }
    }

    if (aggr) {
        if (msg != NULL) {
            p = aggr->cur_write;
            memcpy((char *) p, (char *) msg, MSG_SERVER_SIZE); 
            aggr->cur_write = p + MSG_SERVER_SIZE;
            aggr->num = aggr->num + 1;
        } else {
            if (aggr->num == 0) {
                return;
            }
        }

        if (aggr->num == COMB_MAX_NUM) {
            is_send = 1;
        } else if (aggr->access_time < tc_current_time_sec) {
            is_send = 1;
        } else if (aggr->access_time == tc_current_time_sec) {
            if (aggr->access_msec != tc_current_time_msec) {
                is_send = 1;
            }
        }

        if (is_send) {
            tc_log_debug1(LOG_DEBUG, 0, "combined send:%d", aggr->num);
            aggr->num = htons(aggr->num);
            p = (unsigned char *) (&(aggr->num));
            bytes = aggr->cur_write - aggr->aggr_resp + sizeof(aggr->num);
            tc_log_debug1(LOG_DEBUG, 0, "send bytes:%d", bytes);
            ret = tc_socket_send(fd, (char *) p, bytes);
            aggr->num = 0;
            aggr->cur_write = aggr->aggr_resp;
        } 

        aggr->access_time = tc_current_time_sec;
        aggr->access_msec = tc_current_time_msec;

        if (ret == TC_ERROR) {
            tc_intercept_release_tunnel(fd, NULL);
        }
    }
}
예제 #25
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;
    }
}
예제 #26
0
static void         
retrieve_options(tc_user_t *u, int direction, tc_tcp_header_t *tcp_header)
{                   
    uint32_t       ts_value; 
    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_WSCALE:
                if ((p + 1) >= end) {
                    return;
                }
                opt_len = p[1];
                if ((p + opt_len) > end) {
                    return;
                }
                u->wscale = (uint16_t) p[2];
                p += opt_len;
            case TCPOPT_TIMESTAMP:
                if ((p + 1) >= end) {
                    return;
                }
                opt_len = p[1];
                if ((p + opt_len) > end) {
                    return;
                }
                if (direction == LOCAL) {
                    ts_value = EXTRACT_32BITS(p + 2);
                } else {
                    u->ts_ec_r  = EXTRACT_32BITS(p + 2);
                    ts_value = EXTRACT_32BITS(p + 6);
                    if (tcp_header->syn) {
                        u->state.timestamped = 1;
                        tc_log_debug1(LOG_DEBUG, 0, "timestamped,p=%u", 
                                ntohs(u->src_port));
                    }
                    tc_log_debug3(LOG_DEBUG, 0, 
                            "get ts(client viewpoint):%u,%u,p:%u", 
                            u->ts_value, u->ts_ec_r, ntohs(u->src_port));
                }
                if (ts_value > u->ts_value) {
                    tc_log_debug1(LOG_DEBUG, 0, "ts > history,p:%u",
                            ntohs(u->src_port));
                    u->ts_value = ts_value;
                }
                p += opt_len;
            case TCPOPT_NOP:
                p = p + 1; 
                break;                      
            case TCPOPT_EOL:
                return;
            default:
                if ((p + 1) >= end) {
                    return;
                }
                opt_len = p[1];
                p += opt_len;
                break;
        }    
    }

    return;
}
예제 #27
0
파일: main.c 프로젝트: leek2hu/wtcpcopy
static int
retrieve_clt_tf_ips()
{
    int          count = 0, len, i;
    char        *split, *p, tmp_ip[32], *q;
    uint32_t     ip;

    p = clt_settings.raw_clt_tf_ip;

    while (true) {
        split = strchr(p, ',');
        if (split != NULL) {
            *split = '\0';
        }

        len = strlen(p);
        if (len == 0) {
            tc_log_info(LOG_WARN, 0, "ip is empty");
            break;
        }

        if (p[len - 1] == 'x') {
            strncpy(tmp_ip, p, len -1);
            q = tmp_ip + len - 1;
            for (i = 1; i < 255; i++) {
                sprintf(q, "%d", i);
                ip = inet_addr(tmp_ip);
                tc_log_debug1(LOG_DEBUG, 0, "clt ip addr:%s", tmp_ip);
                if (check_client_ip_valid(ip)) {
                    clt_settings.clt_tf_ip[count++] = ip;
                    if (count == M_IP_NUM) {
                        tc_log_info(LOG_WARN, 0, "reach limit for clt ips");
                        break;
                    }
                }
            }
        } else if (p[len - 1] == '*') {
            tc_log_info(LOG_ERR, 0, "%s not valid, use x instead of *", p);
            fprintf(stderr, "%s not valid, use x instead of *\n", p);
        } else {
            ip = inet_addr(p);
            if (check_client_ip_valid(ip)) {
                clt_settings.clt_tf_ip[count++] = ip;
                if (count == M_IP_NUM) {
                    tc_log_info(LOG_WARN, 0, "reach limit for clt ips");
                    break;
                }
            }
        }

        if (split != NULL) {
            *split = ',';
        }

        if (count == M_IP_NUM) {
            tc_log_info(LOG_WARN, 0, "reach the limit for clt_tf_ip");
            break;
        }

        if (split == NULL) {
            break;
        } else {
            p = split + 1;
        }

    }

    clt_settings.clt_tf_ip_num = count;

    return 1;
}
예제 #28
0
파일: manager.c 프로젝트: jbli/udpcopy
static int dispose_packet(char *recv_buf, int recv_len, int *p_valid_flag)
{
    int            replica_num, i, last, packet_num, max_payload,
                   index, payload_len;
    char          *packet, tmp_buf[RECV_BUF_SIZE];
    bool           packet_valid = false;
    uint16_t       id, size_ip, size_udp, tot_len, cont_len, pack_len, head_len;
    struct udphdr *udp_header;
    struct iphdr  *ip_header;

    packet = recv_buf;
    if (is_packet_needed((const char *)packet)){
        replica_num = clt_settings.replica_num;
        packet_num = 1;
        ip_header   = (struct iphdr*)packet;
        if (localhost == ip_header->saddr){
            if (0 != clt_settings.lo_tf_ip){
                ip_header->saddr = clt_settings.lo_tf_ip;
            }
        }
        /* 
         * If packet length larger than MTU, then we split it. 
         * This is to solve the ip fragmentation problem
         */
        if (recv_len > clt_settings.mtu){
            /* Calculate number of packets */
            size_ip     = ip_header->ihl << 2;
            tot_len     = ntohs(ip_header -> tot_len);
            if (tot_len != recv_len){
                log_info(LOG_WARN, "packet len:%u, recv len:%u",
                        tot_len, recv_len);
                return FAILURE;
            }
            udp_header  = (struct udphdr*)((char *)ip_header + size_ip);
            size_udp    = ntohs(udp_header->len);
            cont_len    = size_udp - sizeof(struct udphdr);
            head_len    = size_ip + sizeof(struct udphdr);
            max_payload = clt_settings.mtu - head_len;
            packet_num  = (cont_len + max_payload - 1)/max_payload;
            last        = packet_num - 1;
            id          = ip_header->id;
            tc_log_debug1(LOG_INFO, "recv:%d, more than MTU", recv_len);
            index = head_len;
            for (i = 0 ; i < packet_num; i++){
                if (i != last){
                    pack_len = clt_settings.mtu;
                }else{
                    pack_len += (cont_len - packet_num * max_payload);
                }
                payload_len = pack_len - head_len; 
                udp_header->len    = htons(pack_len - size_ip);
                ip_header->tot_len = htons(pack_len);
                ip_header->id = id++;
                /* Copy header here */
                memcpy(tmp_buf, recv_buf, head_len);
                /* Copy payload here */
                memcpy(tmp_buf + head_len, recv_buf + index, payload_len);
                index = index + payload_len;
                if (replica_num > 1){
                    packet_valid = process_packet(true, tmp_buf, pack_len);
                    replicate_packs(tmp_buf, pack_len, replica_num);
                }else{
                    packet_valid = process_packet(false, tmp_buf, pack_len);
                }
            }
        }else{
            if (replica_num > 1){
                packet_valid = process_packet(true, packet, recv_len);
                replicate_packs(packet, recv_len, replica_num);
            }else{
                packet_valid = process_packet(false, packet, recv_len);
            }
        }
    }
    if (packet_valid){
        *p_valid_flag = 1;
    } else {
        *p_valid_flag = 0;
    }
    return SUCCESS;
}
예제 #29
0
파일: tc_router.c 프로젝트: macaww/tcpcopy
/* update router table */
void
router_update(int main_router_fd, tc_ip_header_t *ip_header, int len)
{
#if (!TCPCOPY_SINGLE)
    void                   *fd;
    uint64_t                key;
#endif
    uint32_t                size_ip;
    msg_server_t            msg;
    tc_tcp_header_t        *tcp_header;

#if (TCPCOPY_SINGLE)
    if (main_router_fd == 0) {
        return;
    }
#endif
    if (ip_header->protocol != IPPROTO_TCP) {
        tc_log_info(LOG_INFO, 0, "this is not a tcp packet");
        return;
    }

    size_ip    = ip_header->ihl << 2;
    tcp_header = (tc_tcp_header_t *) ((char *) ip_header + size_ip);

    tc_log_debug1(LOG_DEBUG, 0, "router update:%u", ntohs(tcp_header->source));
    memcpy(&msg, ip_header, len);

#if (!TCPCOPY_SINGLE)
    key = get_key(ip_header->daddr, tcp_header->dest);
    pthread_mutex_lock(&mutex);

    fd  = hash_find(table, key);
    if (fd == NULL) {
        if (!tcp_header->syn) {
            tc_log_info(LOG_NOTICE, 0, "fd is null after session is created");
            tc_log_trace(LOG_NOTICE, 0,  BACKEND_FLAG, ip_header, tcp_header); 
        }
        tc_log_debug0(LOG_DEBUG, 0, "fd is null");
        fd_null_cnt++;
        delay_table_add(key, &msg);

        pthread_mutex_unlock(&mutex);

        return ;
    }

    pthread_mutex_unlock(&mutex);
#endif

    tc_log_debug_trace(LOG_NOTICE, 0,  BACKEND_FLAG, ip_header, tcp_header);

#if (INTERCEPT_COMBINED)

#if (!TCPCOPY_SINGLE)
    buffer_and_send(main_router_fd, (int) (long) fd, &msg);
#else
    buffer_and_send(main_router_fd, main_router_fd, &msg);
#endif

#else

#if (!TCPCOPY_SINGLE)
    tc_socket_send((int) (long) fd, (char *) &msg, MSG_SERVER_SIZE);
#else
    tc_socket_send(main_router_fd, (char *) &msg, MSG_SERVER_SIZE);
#endif

#endif

}