Exemple #1
0
/*
 * filter packets 
 */
bool is_packet_needed(const char *packet)
{
    bool           is_needed = false;
    uint16_t       size_ip, size_udp, tot_len;
    struct iphdr  *ip_header;
    struct udphdr *udp_header;

    ip_header = (struct iphdr*)packet;

    /* check if it is a udp packet */
    if(ip_header->protocol != IPPROTO_UDP){
        return is_needed;
    }

    size_ip   = ip_header->ihl << 2;
    tot_len   = ntohs(ip_header->tot_len);
    if (size_ip < 20) {
        log_info(LOG_WARN, "Invalid IP header length: %d", size_ip);
        return is_needed;
    }

    udp_header = (struct udphdr*)((char *)ip_header + size_ip);
    size_udp   = ntohs(udp_header->len);
    if (size_udp < sizeof(struct udphdr)) {
        log_info(LOG_WARN, "Invalid udp header len: %d bytes,pack len:%d",
                size_udp, tot_len);
        return is_needed;
    }

    /* filter the packets we do care about */
    if(LOCAL == check_pack_src(&(clt_settings.transfer), 
                ip_header->daddr, udp_header->dest, CHECK_DEST)){
        is_needed = true;
        clt_udp_cnt++;
        strace_pack(LOG_DEBUG, ip_header, udp_header);
    }

    return is_needed;

}
Exemple #2
0
static int dispose_packet(char *recv_buf, int recv_len, int *p_valid_flag)
{
    char     *packet, tmp_buf[RECV_BUF_SIZE];
    int      replica_num, i, last, packet_num, max_payload;
    int      index, payload_len;
    bool     packet_valid = false;
    uint16_t id, size_ip, size_tcp, tot_len, cont_len, pack_len, head_len;
    uint32_t seq;
    struct tcphdr *tcp_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;
            }
            tcp_header  = (struct tcphdr*)((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)
            strace_pack(LOG_NOTICE, CLIENT_FLAG, ip_header, tcp_header);
#endif
            tc_log_debug1(LOG_INFO, "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(packet_valid){
        *p_valid_flag = 1;
    }
    return SUCCESS;
}