2012-09-06 28 views
5

Tôi là phần mềm lập trình có thể gửi gói tcp tới máy chủ lưu trữ.Làm cách nào để đặt các tùy chọn TCP để gửi gói?

Tôi có thể tạo gói có tiêu đề IP, tiêu đề TCP và dữ liệu nhưng tôi không thể quản lý cách thêm tùy chọn TCP như MSS, NOP, STACK, Tỷ lệ cửa sổ hoặc Dấu thời gian.

Tôi có nghĩa là tôi không thể thêm tùy chọn vào tiêu đề TCP, tính toán tổng kiểm tra chính xác để gửi gói TCP tốt đến máy chủ lưu trữ.

Tôi chỉ có thể gửi các gói TCP đúng mà không có tùy chọn TCP.

Bạn có nghĩ rằng tôi đang sử dụng đúng bản vá không? Ai đó có thể giúp tôi được không?

/* TCP Header structure */ 
struct tcphdr 
{ 
    u_int16_t th_sport;   /* source port */ 
    u_int16_t th_dport;   /* destination port */ 
    u_int32_t th_seq;    /* sequence number */ 
    u_int32_t th_ack;    /* acknowledgement number */ 
#if __BYTE_ORDER == __LITTLE_ENDIAN 
    u_int8_t th_x2:4;   /* (unused) */ 
    u_int8_t th_off:4;   /* data offset */ 
#endif 
#if __BYTE_ORDER == __BIG_ENDIAN 
    u_int8_t th_off:4;   /* data offset */ 
    u_int8_t th_x2:4;   /* (unused) */ 
#endif 
    u_int8_t th_flags; 
    # define TH_FIN  0x01 
    # define TH_SYN  0x02 
    # define TH_RST  0x04 
    # define TH_PUSH  0x08 
    # define TH_ACK  0x10 
    # define TH_URG  0x20 
    # define TH_ECE  0x40 
    # define TH_CWR  0x80 
    u_int16_t th_win;    /* window */ 
    u_int16_t th_sum;    /* checksum */ 
    u_int16_t th_urp;    /* urgent pointer */ 
}; 

struct tcp_option_mss 
{ 
    uint8_t  kind;    /* 2 */ 
    uint8_t  len;    /* 4 */ 
    uint16_t mss; 
}   __attribute__((packed)); 

struct tcphdr_mss 
{ 
    struct tcphdr  tcphdr; 
    struct tcp_option_mss mss; 
}; 

/* IP Header structure */ 

struct ip 
{ 
#if __BYTE_ORDER == __LITTLE_ENDIAN 
    unsigned int ip_hl:4;    /* header length */ 
    unsigned int ip_v:4;    /* version */ 
#endif 
#if __BYTE_ORDER == __BIG_ENDIAN 
    unsigned int ip_v:4;    /* version */ 
    unsigned int ip_hl:4;    /* header length */ 
#endif 
    u_int8_t ip_tos;     /* type of service */ 
    u_short  ip_len;      /* total length */ 
    u_short  ip_id;      /* identification */ 
    u_short  ip_off;      /* fragment offset field */ 
    # define IP_RF 0x8000    /* reserved fragment flag */ 
    # define IP_DF 0x4000    /* dont fragment flag */ 
    # define IP_MF 0x2000    /* more fragments flag */ 
    # define IP_OFFMASK 0x1fff   /* mask for fragmenting bits */ 
    u_int8_t ip_ttl;     /* time to live */ 
    u_int8_t ip_p;      /* protocol */ 
    u_short  ip_sum;      /* checksum */ 
    struct in_addr ip_src, ip_dst;  /* source and dest address */ 
}; 


int send_packet(int sock, long dest_ip , long source_ip, long port, u_int8_t th_flags, unsigned long seq, unsigned long ack, unsigned long port1, unsigned char * data, unsigned long data_i) 
{ 
    char     * packet; 

    struct ip    * pkt_ip; 
    struct tcphdr    * pkt_tcp; 
    struct tcphdr_mss   * tcp_header; 
    struct sockaddr_in    sin; 

    packet = malloc(sizeof(struct ip) + sizeof(struct tcphdr_mss) + data_i); 

    if (packet == NULL) 
    { 
     if (ECHO) 
      fprintf(stderr, "Error in allocating memory\n"); 
     exit(EXIT_FAILURE); 
    } 

    memset(packet, 0, sizeof(struct ip) + sizeof(struct tcphdr_mss)); 

    pkt_ip    = (struct ip *)  packet; 
    pkt_tcp    = (struct tcphdr *) (packet + sizeof(struct ip)); 

    pkt_tcp->th_sport  = htons(port1); 
    pkt_tcp->th_dport  = htons(port); 
    pkt_tcp->th_seq   = htonl(seq); 
    pkt_tcp->th_ack   = htonl(ack); 
    pkt_tcp->th_off   = sizeof(struct tcphdr)/4 + 1; 
    pkt_tcp->th_flags  = th_flags; 
    pkt_tcp->th_win   = htons(32768); 
    pkt_tcp->th_sum   = 0; 

    tcp_header   = malloc(sizeof(struct tcphdr)); 
    tcp_header->tcphdr  = *pkt_tcp; 
    tcp_header->mss.kind  = 2; 
    tcp_header->mss.len  = 4; 
    tcp_header->mss.mss  = htons(32000); 

    pkt_ip->ip_v   = 4; 
    pkt_ip->ip_hl   = sizeof(struct ip) >> 2; 
    pkt_ip->ip_tos   = 0; 
    pkt_ip->ip_len   = htons(sizeof(struct ip) + sizeof(struct tcphdr) + data_i); 

    if (ipid > 65000) 
     ipid = 0; 
    ipid++; 
    pkt_ip->ip_id   = ipid; 
    pkt_ip->ip_off   = 0; 
    pkt_ip->ip_ttl   = 64; 
    pkt_ip->ip_p   = IPPROTO_TCP ; 
    pkt_ip->ip_sum   = 0; 
    pkt_ip->ip_src.s_addr  = source_ip; 
    pkt_ip->ip_dst.s_addr  = dest_ip; 

    pkt_ip->ip_sum   = checksum((unsigned short*)pkt_ip, sizeof(struct ip)); 
    pkt_tcp->th_sum   = in_cksum_tcp(pkt_ip->ip_src.s_addr, pkt_ip->ip_dst.s_addr, (unsigned short *) pkt_tcp, sizeof(struct tcphdr_mss), data, data_i); 

    memcpy(((char *)pkt_tcp + sizeof(struct tcphdr_mss)), data, data_i); 

    memset(&sin, 0, sizeof(sin)); 
    sin.sin_family   = AF_INET; 
    sin.sin_addr.s_addr  = pkt_ip->ip_dst.s_addr; 

    if (sendto(sock, packet, sizeof(struct ip) + sizeof(struct tcphdr_mss) + data_i, 0, (struct sockaddr *) &sin, sizeof(sin)) < 0) 
    { 
     perror("sendto"); 
     free(packet); 
     return -1; 
    } 

    free(packet); 

    return 0; 
} 
+1

Xác định "không thể quản lý". Chưa có câu hỏi thực sự nào ở đây. – EJP

+0

Bạn đang cố gửi một gói IP thô _just_ để đặt các tùy chọn đó? – Alnitak

+0

Tôi đang cố gắng gửi một gói TCP với các tùy chọn để thiết lập kết nối. – Shark

Trả lời

0

Trong dòng:

pkt_tcp->th_sum   = in_cksum_tcp(pkt_ip->ip_src.s_addr, pkt_ip->ip_dst.s_addr, (unsigned short *) pkt_tcp, sizeof(struct tcphdr_mss), data, data_i); 

Theo chức năng in_cksum_tcp mà tôi đã nhìn thấy trong tự nhiên:

unsigned short in_cksum_tcp(int src, int dst, unsigned short *addr, int len, unsigned char * data, int data_i) 

Bạn đang đi qua các kích thước của các tùy chọn tiêu đề (sizeof (struct tcphdr_mss)), thay vì kích thước của tiêu đề TCP hoàn chỉnh (sizeof (tcphdr) + sizeof (tcphdr_mss)). Tôi nghĩ rằng đây có thể là vấn đề (bạn không tính toán đúng TCP checksum).

Một cách hay để kiểm tra đó là vấn đề tạo gói dữ liệu thô là lưu gói với libpcap vào tệp pcap và mở bằng công cụ đánh dấu. Bạn có thể kiểm tra dễ dàng tính toàn vẹn của gói tin.

1

Dưới đây là một chức năng mà tính toán checksum chính xác cho một gói

unsigned short csum(unsigned short * ptr, int nbytes) { 
    register long sum; 
    unsigned short oddbyte; 
    register short answer; 

    sum = 0; 
    while (nbytes > 1) { 
     sum += * ptr++; 
     nbytes -= 2; 
    } 
    if (nbytes == 1) { 
     oddbyte = 0; * ((u_char *) & oddbyte) = * (u_char *) ptr; 
     sum += oddbyte; 
    } 

    sum = (sum >> 16) + (sum & 0xffff); 
    sum = sum + (sum >> 16); 
    answer = (short)~sum; 

    return (answer); 
} 

cuộc gọi chức năng để có được checksum cho ip và tcp. khác sau đó inorder này để sử dụng tùy chọn như các tùy chọn như MSS, NOP, STACK bạn cần phải khai báo tất cả điều này trong tiêu đề TCP của bạn. và khi bạn đang sử dụng tất cả điều này trong chương trình của mình, bạn phải đặt giá trị của th_off tương ứng

Các vấn đề liên quan