2012-09-06 43 views
5

我是可以發送tcp數據包到主機的編程軟件。如何設置發送數據包的TCP選項?

我能夠創建一個IP報頭,TCP頭和數據包,但我無法管理如何添加TCP選項,如MSS,NOP,堆棧,窗口縮放或時間戳。

我的意思是我不能將選項添加到TCP標頭,計算出正確的校驗和以發送一個好的TCP數據包到主機。

我可以在沒有TCP選項的情況下發送正確的TCP數據包。

你覺得我在正確的補丁嗎?有人可以幫我嗎?

/* 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

定義「無法管理」。這裏沒有真正的問題。 – EJP

+0

您是否嘗試發送原始IP數據包_just_來設置這些選項? – Alnitak

+0

我正在嘗試發送一個帶有選項的TCP數據包來建立連接。 – Shark

回答

0

在行:

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); 

根據我在野外見過in_cksum_tcp功能:

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

你傳入的選項報頭的大小(的sizeof (struct tcphdr_mss)),而不是完整的TCP頭部(sizeof(tcphdr)+ sizeof(tcphdr_mss))的大小。我認爲這可能是問題(你不能正確計算TCP校驗和)。

一個很好的方法來檢查是否是創建原始數據包的問題是將數據包與libpcap保存到pcap文件並使用wireshark打開。您可以輕鬆檢查數據包的完整性。

1

下面是計算正確的校驗和的包

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); 
} 

調用該函數來獲取IP和TCP校驗功能。 其他然後這個爲了使用像MSS,NOP,STACK這樣的選項你需要在你的TCP頭中聲明所有這些選項。當你在你的程序中使用所有這些時,你必須相應地設置th_off的值