我正在尝试获取正确的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) –