2012-01-13 139 views
4

我一直在做幾天的TCP校驗和。我已經查看了互聯網上的許多來源,但是我沒有看到任何示例向您展示如何執行TCP校驗和。我也看了看RFC文件,仍然我有麻煩:C編程TCP校驗和

下面是我使用生成的校驗碼:

unsigned short checksum(unsigned short * buffer, int bytes) 
{ 
    unsigned long sum = 0; 
    unsigned short answer = 0; 
    int i = bytes; 
    while(i>0) 
    { 
      sum+=*buffer; 
      buffer+=1; 
      i-=2; 
    } 
    sum = (sum >> 16) + (sum & htonl(0x0000ffff)); 
    sum += (sum >> 16); 
    return ~sum; 
} 

此功能適用於IP校驗和。

下面是我爲我的TCP報頭所做的結構:

struct tcp_header 
{ 
    unsigned short tcp_sprt; 
    unsigned short tcp_dprt; 
    unsigned int tcp_seq; 
    unsigned int tcp_ack; 
    unsigned char tcp_res:4; 
    unsigned char tcp_off:4; 
    unsigned char tcp_flags; 
    unsigned short tcp_win; 
    unsigned short tcp_csum; 
    unsigned short tcp_urp; 
}; 

我一直在使用Wireshark來測試這些數據包,唯一錯的是校驗碼。

最後這裏是僞報頭結構,我從IP報頭中的TCP報頭和信息加載:

struct pseudoTcpHeader 
{ 
    unsigned int ip_src; 
    unsigned int ip_dst; 
    unsigned char zero;//always zero 
    unsigned char protocol;// = 6;//for tcp 
    unsigned short tcp_len; 
    struct tcp_header tcph; 
}; 

一旦我加載了這個結構用正確的信息然後我就用校驗功能整個僞頭結構並將TCP校驗和分配給該值。你看到我提供的東西有什麼不對嗎?如果問題不在這裏,可能是我看不到的一個粗心的錯誤。

+0

如何將信息加載到結構中以及它來自哪裏? – 2012-01-13 02:36:15

回答

4

我發現了winpcap-users mailing list應該解決Greg的約奇數長度數據的註釋,並給你的東西來比較你的代碼對一個非常好的例子。

USHORT CheckSum(USHORT *buffer, int size) 
{ 
    unsigned long cksum=0; 
    while(size >1) 
    { 
     cksum+=*buffer++; 
     size -=sizeof(USHORT); 
    } 
    if(size) 
     cksum += *(UCHAR*)buffer; 

    cksum = (cksum >> 16) + (cksum & 0xffff); 
    cksum += (cksum >>16); 
    return (USHORT)(~cksum); 
} 
3

我看到一對夫婦的事情:

  • 你不是被填充零佔奇數長度的數據。
  • 從數據包中讀取每個單詞時,您需要考慮網絡字節順序。
  • 您使用htonl(0x0000ffff)似乎是可疑的。爲什麼你要將一個常量轉換爲網絡字節順序與主機字節順序中的數據結合起來?
2

RFC 793說「如果一個段包含要校驗和奇數的標題和文本八位字節,最後一個八位字節是在用零權以形成用於校驗目的的16位字填充」。上面的代碼不處理這種情況。我認爲循環條件應該是i> 1,然後檢查循環外的i == 1,併爲最後一個八位字節執行特殊處理。