我正在嘗試獲取正確的TCP校驗和,但失敗。我正在使用C++,我用winpcap獲取本地網絡的數據包,並試圖計算它們的tcp校驗和(我已經把正確的過濾器設置爲只有tcp數據包)。但是當我比較我的計算校驗和與wireshark tcp校驗和時,它們是不一樣的。TCP校驗和計算出錯
這是我用C++做的代碼,它使用位圖來檢測位承載。
u_char* tcp_checksum(const u_char* data, int size)
{
u_char *checksum = new u_char[2]();
uint16_t sumando = 0;
bitset<17> total;
//add ip src and ip dst
for (int i = 26; i < 33; i++){
total = sumando + (uint16_t)((datos[i] << 8) + datos[i + 1]);
sumando += (uint16_t)((datos[i] << 8) + datos[i + 1]);
if (total[16] == 1)
sumando++;
i++;
}
//add el zero byte and number of protocol
total = sumando + (uint16_t)(0x06);
sumando += (uint16_t)(0x06);
if (total[16] == 1)
sumando++;
/*here I should add the tcp length to complete the tcp pseudo header but i didnt add anything because I dont know to calculate the tcp len correctly but its not a problem because a lot of times is cero and the tcp still failing.*/
//okay we have just calculated the pseudoheader.
//add all tcp header except the 2 bytes of the checksum (20 bytes normally)
for (int i = 34; i < 54; i++){
if (i != 50 && i != 52){//no sumo ni padding ni checksum.
total = sumando + (uint16_t)((datos[i] << 8) + datos[i + 1]);
sumando += (uint16_t)((datos[i] << 8) + datos[i + 1]);
if (total[16] == 1)
sumando++;
}
//
if (i == 52) break;
i++;
}
//add the tcp payload in 16 bits each adding.
for (int i = 55; i < tamaño - 1; i++){//tamaño - 1
total = sumando + (uint16_t)((datos[i] << 8) + datos[i + 1]);
sumando += (uint16_t)((datos[i] << 8) + datos[i + 1]);
if (total[16] == 1)
sumando++;
i++;
}
if (tamaño % 2 == 0){
total = sumando + (uint16_t)((0x00 << 8) + datos[tamaño]);
sumando += (uint16_t)((0x00 << 8) + datos[tamaño]);
if (total[16] == 1)
sumando++;
}
//i get the complementary and i divided the u_short (16 bits) (uint16_t) in 2 bytes which i return
sumando = sumando & 0xFFFF;
sumando = ~sumando;
checksum[0] = (sumando >> 8) & 0x00FF;
checksum[1] = sumando & 0x00FF;
return checksum;
}
好吧,當我嘗試不是真正的TCP校驗字節和我的TCP校驗其之間比較相同:
printf("%x%x==", pkt_data[50], pkt_data[51]); u_char *c = new u_char[2](); c= tcp_checksum(pkt_data, header->caplen); printf("%x%x\n", c[0], c[1]); cout << endl; delete c;
我得到不同的字節,通常字節51和52一個數據包的tcp屬於tcp校驗和。當我輸出它們時,它們是不一樣的。
難道你不能將你的校驗碼與Wireshark在用戶空間中做什麼比較,或者檢查linux內核並看看它是如何完成的? –
這不是問題,因爲我讀過「校驗和卸載」也會影響IP校驗和,在這種情況下,我使用相同的方法計算了IP校驗和,結果是成功的。問題出在代碼中,所以請關注代碼,而不要關注不存在的問題。我的代碼是錯誤的,我在這裏發佈它來糾正它,而不是當我的代碼有100個錯誤沒有被糾正時談論「校驗和卸載」。 – Kaxperday
你是否遵循RFC?請參閱[TCP校驗和功能設計](https://tools.ietf.org/html/rfc1071#section-2.4.4.5) –