我再次在这里计算TCP校验和。
我需要添加pseudoheader tcp + tcp header + tcp payload。 所有必须以16位的形式添加,如您所知。
在我的代码中,我做的第一件事就是添加到" sumando" (加载校验和的变量)伪头。 之后,我将标头tcp从unsigned short添加到unsigned short。 之后,我将有效负载tcp从unsigned short添加到unsigned short。
最后,我做了tcp校验和的补充,并将其转换为2个字节。它应该是有效的,但它起作用了。
我正在使用winpcap从我的计算机中捕获数据包并重新计算tcp校验和。打开wireshark,你可以看到哪个字节开始字段。
//http://www.arcesio.net/checksum/checksumTCP.html
u_char* tcp_checksum(const u_char* _datos, int _tamaño)
{
u_char *checksum = new u_char[2];
u_short sumando = 0, sumanda = 0;
bitset<17> controlador;
if (_tamaño < 54)
return nullptr;
//sumo ip origen e ip destino
for (int i = 26; i < 33; i++){
sumanda = (u_short)((_datos[i] << 8) + _datos[i + 1]);
controlador = sumando + sumanda;
sumando += sumanda;
if (controlador[16] == 1)
sumando++;
i++;
}
//sumo el byte de ceros y el numero de protocolo TCP
sumanda = (u_short)0x06;
controlador = sumando + sumanda;
sumando += sumanda;
if (controlador[16] == 1)
sumando++;
//sumamos el tcp segment len
sumanda = (u_short)((_datos[16] << 8) + _datos[17]) - ((u_short)((_datos[46] & 0xF0) >> 4) +
(u_short)(_datos[14] & 0x0F)) * 4;
//cout << "tcpseglen: " << sumanda;
cout << " tamaño: " << _tamaño << " ";
controlador = sumando + sumanda;
sumando += sumanda;
if (controlador[16] == 1)
sumando++;
//YA TENEMOS SUMADO EL PSEUDO HEADER BIEEEEEN
//sumo todo el campo de cabecera con el checksum a cero
for (int i = 34; i < 53; i++){
if (i != 50){
sumanda = (u_short)((_datos[i] << 8) + _datos[i + 1]);
controlador = sumando + sumanda;
sumando += sumanda;
if (controlador[16] == 1)
sumando++;
}
i++;
}
//suponiendo un tamaño de 20 bytes de cabecera siempre..
//sumo todo el payload tcp
for (int i = 54; i < _tamaño; i++){
if (i + 1 == _tamaño && _tamaño % 2 == 0){//se desborda entonces copiamos solo el ultimo, pero estará ya copiado??
sumanda = (u_short)_datos[_tamaño - 1];
controlador = sumando + sumanda;
sumando += sumanda;
if (controlador[16] == 1)
sumando++;
break;
}
sumanda = (u_short)((_datos[i] << 8) + _datos[i + 1]);
controlador = sumando + sumanda;
sumando += sumanda;
if (controlador[16] == 1)
sumando++;
i++;
}
u_short original;
original = (_datos[50] << 8) + _datos[51];
sumando += 20;
sumando = sumando & 0xFFFF;
sumando = ~sumando;
//cout << "checksum original: " << original << endl;
//cout << "checksum calculado: " << sumando << endl;
checksum[0] = (sumando >> 8) & 0x00FF;
checksum[1] = sumando & 0x00FF;
return checksum;
}
我将tcp数据包传递给此函数(使用winpcap捕获数据包)。 我将我的tcp校验和与数据包的实际tcp校验和进行比较,这分别是输出,原始tcp cheksum和mine tcp校验和的示例:
6e9==6e9
75a==75a
fe1e==fe1e
8c3e==8c3e
73ed==73ed
8a52==8a52
844d==841d
dad2==dac4
5cde==5cde
e2d1==e2d1
当数据包不是奇数我只需要添加20到我的cheksum得到原始我不知道为什么但它的工作..但我不想明显做,如果数据包是奇数校验和之间的区别是不是常数。
我的代码出了什么问题?请帮忙。
Regardes Kaxper!